Skip to content

Commit

Permalink
Merge pull request #28 from 1000TurquoisePogs/bugfix/close-handler
Browse files Browse the repository at this point in the history
Reorganized close listener for Apps to be a viewport event
  • Loading branch information
1000TurquoisePogs authored Feb 26, 2019
2 parents 9145bf8 + 2a87f2b commit 3e3a844
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@ export class ViewportManager implements MVDHosting.ViewportManagerInterface {
private viewports: Map<MVDHosting.ViewportId, Viewport>;
private viewportInstances: Map<MVDHosting.ViewportId, MVDHosting.InstanceId>;
private readonly logger: ZLUX.ComponentLogger = BaseLogger;

private closeHandlers: Map<MVDHosting.ViewportId, Array<() => Promise<any>>>;
constructor() {
this.viewports = new Map();
this.viewportInstances = new Map();
this.closeHandlers = new Map();
}

createViewport(providers: Map<string, any>): MVDHosting.ViewportId {
const viewport = new Viewport(providers);
createViewport(providersProvider: any): MVDHosting.ViewportId {
const viewport = new Viewport(providersProvider);
this.viewports.set(viewport.viewportId, viewport);

return viewport.viewportId;
Expand All @@ -41,9 +42,43 @@ export class ViewportManager implements MVDHosting.ViewportManagerInterface {
this.viewportInstances.set(viewportId, instanceId);
}

destroyViewport(viewportId: MVDHosting.ViewportId): void {
// TODO
registerViewportCloseHandler(viewportId: MVDHosting.ViewportId, handler: () => Promise<any>):void {
let handlers = this.closeHandlers.get(viewportId);
if (!handlers) {
handlers = new Array<() => Promise<any>>();
this.closeHandlers.set(viewportId, handlers);
}
handlers.push(handler);
}

private closeWatcherLoop(pos: number, handlers: Array<() => Promise<any>>, finishedCallback: any, rejectCallback: any): void {
if (pos >= handlers.length) {
finishedCallback();
} else {
handlers[pos]().then(()=> {
this.closeWatcherLoop(++pos, handlers, finishedCallback, rejectCallback);
}).catch((reason:any)=> {
rejectCallback();
});
}
}

destroyViewport(viewportId: MVDHosting.ViewportId): Promise<any> {
// TODO there may be other actions desired for destroyviewport
this.logger.info(`Closing viewport ID=${viewportId}`);
console.log(`Removing viewport id=${viewportId}`);
return new Promise((resolve,reject)=> {
let handlers = this.closeHandlers.get(viewportId);
if (handlers) {
this.closeWatcherLoop(0,handlers,()=> {
resolve();
}, (reason:any)=> {
reject(reason);
});
} else {
resolve();
}
});
}

getApplicationInstanceId(viewportId: MVDHosting.ViewportId): MVDHosting.InstanceId | null {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ export class Viewport {
readonly providers: Map<string, any>;
private readonly logger: ZLUX.ComponentLogger = BaseLogger;

constructor(providers: Map<string, any>) {
constructor(providersProvider: any) {
this.viewportId = Viewport.nextViewportId ++;
this.providers = providers;
this.providers = providersProvider(this.viewportId);

this.checkProviders();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@ export class DesktopWindow {
readonly windowId: MVDWindowManagement.WindowId;
readonly windowState: DesktopWindowState;
readonly localWindowEvents: LocalWindowEvents;
private childViewports: Array<MVDHosting.ViewportId>;
public readonly plugin: ZLUX.Plugin;
viewportId: MVDHosting.ViewportId;
closeHandler: (() => Promise<void>) | null;
viewportId: MVDHosting.ViewportId; //primary, if children exist

closeHandler: (() => Promise<void>) | null; //DEPRECATED 1.0.1, use viewport close handler instead of window

constructor(windowId: MVDWindowManagement.WindowId, windowState: DesktopWindowState, plugin: ZLUX.Plugin) {
this._windowTitle = '';
this.windowId = windowId;
this.windowState = windowState;
this.closeHandler = null;
this.plugin = plugin;
this.childViewports = new Array<MVDHosting.ViewportId>();
this.localWindowEvents = {
windowMaximized: new EventEmitter<void>(true),
windowMinimized: new EventEmitter<void>(true),
Expand Down Expand Up @@ -88,6 +91,41 @@ export class DesktopWindow {
this._windowTitle = value;
this.localWindowEvents.windowTitleChanged.emit(value);
}

addChildViewport(viewportId: MVDHosting.ViewportId): void{
this.childViewports.push(viewportId);
}

closeViewports(viewportManager: MVDHosting.ViewportManagerInterface): Promise<any> {
return new Promise((resolve, reject)=> {
viewportManager.destroyViewport(this.viewportId).then(()=> {
if (this.childViewports.length == 0) {
resolve();
} else {
this.closeViewportLoop(0, viewportManager, ()=> {
resolve();
}, (reason:any)=> {
reject({viewport:this.viewportId, reason:reason});
});
}
}).catch((reason:any)=> {
reject({viewport:this.viewportId, reason:reason});
});
});
}

private closeViewportLoop(pos: number, viewportManager: MVDHosting.ViewportManagerInterface, finishedCallback: any, rejectedCallback: any): void {
if (pos >= this.childViewports.length) {
finishedCallback();
}
else {
viewportManager.destroyViewport(this.childViewports[pos]).then(()=> {
this.closeViewportLoop(++pos,viewportManager,finishedCallback,rejectedCallback);
}).catch((reason:any)=> {
rejectedCallback(reason);
});
}
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,17 @@ export class WindowManagerService implements MVDWindowManagement.WindowManagerSe
setTitle: (title) => this.setWindowTitle(windowId, title),
setPosition: (pos) => this.setPosition(windowId, pos),
spawnContextMenu: (xRel, yRel, items) => this.spawnContextMenu(windowId, xRel, yRel, items),
registerCloseHandler: (handler) => this.registerCloseHandler(windowId, handler)
registerCloseHandler: (handler)=> this.registerCloseHandler(windowId, handler)
};
}

private generateViewportEventsProvider(windowId: MVDWindowManagement.WindowId): Angular2PluginViewportEvents {
private generateViewportEventsProvider(windowId: MVDWindowManagement.WindowId, viewportId: MVDHosting.ViewportId): Angular2PluginViewportEvents {
const events = this.getWindowEvents(windowId);

return {
resized: events.windowResized
resized: events.windowResized,
spawnContextMenu: (xRel, yRel, items) => this.spawnContextMenu(windowId, xRel, yRel, items),
registerCloseHandler: (handler) => this.viewportManager.registerViewportCloseHandler(viewportId, handler)
};
}

Expand All @@ -257,25 +259,30 @@ export class WindowManagerService implements MVDWindowManagement.WindowManagerSe

const viewportComponent = componentRef.instance;

const providers: Map<string, any> = new Map();
providers.set(Angular2InjectionTokens.VIEWPORT_EVENTS, this.generateViewportEventsProvider(windowId));
providers.set(Angular2InjectionTokens.PLUGIN_EMBED_ACTIONS, this.generateEmbedAction(windowId));

viewportComponent.viewportId = this.viewportManager.createViewport(providers);
viewportComponent.viewportId = this.viewportManager.createViewport((viewportId: MVDHosting.ViewportId)=> {
const providers: Map<string, any> = new Map();
providers.set(Angular2InjectionTokens.VIEWPORT_EVENTS, this.generateViewportEventsProvider(windowId, viewportId));
providers.set(Angular2InjectionTokens.PLUGIN_EMBED_ACTIONS, this.generateEmbedAction(windowId));
return providers;
});
const viewportId = viewportComponent.viewportId;
const desktopWindow = this.windowMap.get(windowId);
if (desktopWindow) {
desktopWindow.addChildViewport(viewportId);
}
return this.applicationManager.spawnApplicationWithTarget(plugin, launchMetadata, viewportComponent.viewportId)
.then(instanceId => (<EmbeddedInstance>{instanceId, viewportId}));
});
}
};
}

private generateWindowProviders(windowId: MVDWindowManagement.WindowId): Map<string, any> {
private generateWindowProviders(windowId: MVDWindowManagement.WindowId, viewportId: MVDHosting.ViewportId): Map<string, any> {
const providers: Map<string, any> = new Map();

providers.set(Angular2InjectionTokens.WINDOW_ACTIONS, this.generateWindowActionsProvider(windowId));
providers.set(Angular2InjectionTokens.WINDOW_EVENTS, this.generateWindowEventsProvider(windowId));
providers.set(Angular2InjectionTokens.VIEWPORT_EVENTS, this.generateViewportEventsProvider(windowId));
providers.set(Angular2InjectionTokens.VIEWPORT_EVENTS, this.generateViewportEventsProvider(windowId, viewportId));
providers.set(Angular2InjectionTokens.PLUGIN_EMBED_ACTIONS, this.generateEmbedAction(windowId));

return providers;
Expand Down Expand Up @@ -304,8 +311,9 @@ export class WindowManagerService implements MVDWindowManagement.WindowManagerSe
this.updateWindowPositions(pluginId, windowId, newWindowPosition);

/* Create viewport */
const viewportId = this.viewportManager.createViewport(this.generateWindowProviders(windowId));
desktopWindow.viewportId = viewportId;
desktopWindow.viewportId = this.viewportManager.createViewport((viewportId: MVDHosting.ViewportId)=> {
return this.generateWindowProviders(windowId, viewportId);
});

/* Default window actions */
this.setWindowTitle(windowId, pluginImpl.defaultWindowTitle);
Expand Down Expand Up @@ -387,20 +395,30 @@ export class WindowManagerService implements MVDWindowManagement.WindowManagerSe
closeWindow(windowId: MVDWindowManagement.WindowId): void {
const desktopWindow = this.windowMap.get(windowId);
if (desktopWindow == null) {
this.logger.warn(`Attempted to close null window, ID=${windowId}`);
return;
this.logger.warn(`Attempted to close null window, ID=${windowId}`);
return;
}
this.updateWindowPositions(desktopWindow.plugin.getIdentifier(), windowId, desktopWindow.windowState.position);

let appId = this.viewportManager.getApplicationInstanceId(desktopWindow.viewportId);
if (appId!=null) {
this.applicationManager.killApplication(desktopWindow.plugin, appId);

const closeViewports = ()=> {
desktopWindow.closeViewports(this.viewportManager).then(()=> {
if (appId!=null) {
this.applicationManager.killApplication(desktopWindow.plugin, appId);
}
this.destroyWindow(windowId);
}).catch((info:any)=> {
this.logger.warn(`Window could not be closed because of viewport. Details=`,info);
return;
});
}

let appId = this.viewportManager.getApplicationInstanceId(desktopWindow.viewportId);
if (desktopWindow.closeHandler != null) {
desktopWindow.closeHandler().then(() => this.destroyWindow(windowId));
desktopWindow.closeHandler().then(()=>{closeViewports();});
} else {
this.destroyWindow(windowId);
closeViewports();
}

}

closeAllWindows() :void {
Expand All @@ -411,6 +429,7 @@ export class WindowManagerService implements MVDWindowManagement.WindowManagerSe
}

registerCloseHandler(windowId: MVDWindowManagement.WindowId, handler: () => Promise<void>): void {
this.logger.warn(`windowActions.registerCloseHandler is deprecated. Please use viewportEvents.registerCloseHandler instead.`);
const desktopWindow = this.windowMap.get(windowId);
if (desktopWindow == null) {
this.logger.warn('Attempted to register close handler for null window, ID=${windowId}');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
import { Injectable, Injector, EventEmitter } from '@angular/core';
// import { DesktopPluginDefinition } from 'app/plugin-manager/shared/desktop-plugin-definition';
import { ViewportManager } from 'app/application-manager/viewport-manager/viewport-manager.service';
import { Angular2InjectionTokens, Angular2PluginViewportEvents } from 'pluginlib/inject-resources';
import { ContextMenuItem, Angular2InjectionTokens, Angular2PluginViewportEvents } from 'pluginlib/inject-resources';
import { BaseLogger } from 'virtual-desktop-logger';
import { Subject } from 'rxjs/Subject';

@Injectable()
export class SimpleWindowManagerService implements MVDWindowManagement.WindowManagerServiceInterface {
Expand All @@ -24,19 +25,25 @@ export class SimpleWindowManagerService implements MVDWindowManagement.WindowMan
private applicationManager: MVDHosting.ApplicationManagerInterface;
private pluginDef: MVDHosting.DesktopPluginDefinition;

contextMenuRequested: Subject<{xPos: number, yPos: number, items: ContextMenuItem[]}>;

constructor(
private viewportManager: ViewportManager,
private injector: Injector
) {
this.applicationManager = this.injector.get(MVDHosting.Tokens.ApplicationManagerToken);
this.windowResized = new EventEmitter<{ width: number, height: number }>(true);
this.contextMenuRequested = new Subject();
window.addEventListener('resize', () => this.onResize(), false);
}

createWindow(plugin: MVDHosting.DesktopPluginDefinition): MVDWindowManagement.WindowId {
this.theViewportId = this.viewportManager.createViewport(this.generateWindowProviders());
let windowId = 1;
this.pluginDef = plugin;
return 1;
this.theViewportId = this.viewportManager.createViewport((viewportId: MVDHosting.ViewportId)=> {
return this.generateWindowProviders(windowId, viewportId);
});
return windowId;
}

getWindow(plugin: MVDHosting.DesktopPluginDefinition): MVDWindowManagement.WindowId | null {
Expand All @@ -62,16 +69,22 @@ export class SimpleWindowManagerService implements MVDWindowManagement.WindowMan
return this.theViewportId;
}

private generateWindowProviders(): Map<string, any> {
spawnContextMenu(windowId: MVDWindowManagement.WindowId, xRelative: number, yRelative: number, items: ContextMenuItem[]): void {
this.contextMenuRequested.next({xPos: xRelative, yPos: yRelative, items: items});
}

private generateWindowProviders(windowId: MVDWindowManagement.WindowId, viewportId: MVDHosting.ViewportId): Map<string, any> {
const providers: Map<string, any> = new Map();
providers.set(Angular2InjectionTokens.VIEWPORT_EVENTS, this.generateViewportEventsProvider());
providers.set(Angular2InjectionTokens.VIEWPORT_EVENTS, this.generateViewportEventsProvider(windowId, viewportId));

return providers;
}

private generateViewportEventsProvider(): Angular2PluginViewportEvents {
private generateViewportEventsProvider(windowId: MVDWindowManagement.WindowId, viewportId: MVDHosting.ViewportId): Angular2PluginViewportEvents {
return {
resized: this.windowResized
resized: this.windowResized,
spawnContextMenu: (xRel, yRel, items) => this.spawnContextMenu(windowId, xRel, yRel, items),
registerCloseHandler: (handler: ()=>Promise<any>) => this.viewportManager.registerViewportCloseHandler(viewportId, handler)
};
}

Expand Down
2 changes: 2 additions & 0 deletions virtual-desktop/src/pluginlib/inject-resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export interface Angular2PluginWindowEvents {

export interface Angular2PluginViewportEvents {
readonly resized: Subject<{width: number, height: number}>;
readonly spawnContextMenu: (xPos: number, yPos: number, items: ContextMenuItem[]) => void;
readonly registerCloseHandler: (handler: () => Promise<any>) => void;
}

export interface Angular2PluginEmbedActions {
Expand Down

0 comments on commit 3e3a844

Please sign in to comment.