UNPKG

devexpress-diagram

Version:

DevExpress Diagram Control

241 lines (222 loc) 11.7 kB
import { Shape } from "../Shapes/Shape"; import { DiagramItem } from "../DiagramItem"; import { EventDispatcher } from "../../Utils"; import { Point } from "@devexpress/utils/lib/geometry/point"; import { ModelOperationSettings, DiagramModelOperation } from "../../ModelOperationSettings"; import { Connector, ConnectorPosition } from "../Connectors/Connector"; import { RequestedEntity } from "./Entities/RequestedEntity"; import { AddShapeRequestedEntity, AddShapeEventArgs } from "./Entities/AddShape"; import { DeleteShapeRequestedEntity, DeleteShapeEventArgs } from "./Entities/DeleteShape"; import { DeleteConnectorRequestedEntity, DeleteConnectorEventArgs } from "./Entities/DeleteConnector"; import { AddShapeFromToolboxRequestedEntity, AddShapeFromToolboxEventArgs } from "./Entities/AddShapeFromToolbox"; import { ChangeConnectionRequestedEntity, ChangeConnectionEventArgs } from "./Entities/ChangeConnection"; import { ChangeConnectorPointsRequestedEntity, ChangeConnectorPointsEventArgs } from "./Entities/ChangeConnectorPoints"; import { BeforeChangeShapeTextRequestedEntity, BeforeChangeShapeTextEventArgs } from "./Entities/BeforeChangeShapeText"; import { BeforeChangeConnectorTextRequestedEntity } from "./Entities/BeforeChangeConnectorText"; import { ChangeShapeTextEventArgs, ChangeShapeTextRequestedEntity } from "./Entities/ChangeShapeText"; import { ChangeConnectorTextRequestedEntity } from "./Entities/ChangeConnectorText"; import { PermissionsProviderStorage } from "./PermissionsProviderStorage"; import { ResizeShapeRequestedEntity, IResizeShapeInfo } from "./Entities/ResizeShape"; import { IApiController } from "../../Api/ApiController"; import { ISelectionChangesListener, Selection } from "../../Selection/Selection"; import { IMoveShapeInfo, MoveShapeRequestedEntity } from "./Entities/MoveShape"; import { IModelChangesListener } from "../ModelManipulator"; import { ItemChange } from "../ModelChange"; import { Size } from "@devexpress/utils/lib/geometry/size"; export class PermissionsProvider implements ISelectionChangesListener, IModelChangesListener { apiController: IApiController; operationSettings: ModelOperationSettings; storage: PermissionsProviderStorage; onRequestOperation: EventDispatcher<IPermissionRequestListener> = new EventDispatcher(); private cache: RequestedEntity[] = []; private permissionsLockCount: number = 0; private requestDeleteItems: {[key: string]: DiagramItem} = {}; private updateUICount: number = 0; constructor(apiController: IApiController) { this.apiController = apiController; this.operationSettings = new ModelOperationSettings(); this.storage = new PermissionsProviderStorage(); } notifySelectionChanged(_selection: Selection): void { this.clearCache(); } notifyModelChanged(changes: ItemChange[]) { this.clearCache(); } notifyPageColorChanged(color: number) {} notifyPageSizeChanged(pageSize: Size, pageLandscape: boolean) {} clearCache(operation?: DiagramModelOperation): void { if(operation !== undefined) this.cache = this.cache.filter(entry => entry.operation !== operation); else this.cache = []; } canDeleteItems(items: DiagramItem[]): boolean { let allowed = true; items.forEach((item) => { let entity: RequestedEntity; if(item instanceof Shape) entity = new DeleteShapeRequestedEntity(this.apiController, item); if(item instanceof Connector) entity = new DeleteConnectorRequestedEntity(this.apiController, item); allowed = allowed && this.requestOperation(entity); }); return allowed; } canAddItems(items: DiagramItem[]): boolean { let allowed = true; items.forEach((item) => { if(item instanceof Shape) allowed = allowed && this.requestOperation(new AddShapeRequestedEntity(this.apiController, item)); if(item instanceof Connector) { allowed = allowed && this.canChangeConnection(item, item.beginItem, undefined, ConnectorPosition.Begin, item.beginConnectionPointIndex); allowed = allowed && this.canChangeConnection(item, item.endItem, undefined, ConnectorPosition.End, item.endConnectionPointIndex); } }); return allowed; } canAddShapeFromToolbox(itemType: string): boolean { return this.requestOperation(new AddShapeFromToolboxRequestedEntity(this.apiController, itemType)); } canChangeConnection(connector: Connector, item: DiagramItem, oldItem: DiagramItem, position: ConnectorPosition, connectionPointIndex: number): boolean { if(connector && this.requestDeleteItems[connector.key]) return true; if(item === undefined || item === null || item instanceof Shape) return this.requestOperation(new ChangeConnectionRequestedEntity(this.apiController, connector, item as Shape, oldItem as Shape, position, connectionPointIndex)); return true; } canChangeConnectorPoints(connector: Connector, oldPoints: Point[], points: Point[]): boolean { if(connector && this.requestDeleteItems[connector.key]) return true; return this.requestOperation(new ChangeConnectorPointsRequestedEntity(this.apiController, connector, oldPoints, points)); } canChangeShapeText(shape: Shape): boolean { return this.requestOperation(new BeforeChangeShapeTextRequestedEntity(this.apiController, shape)); } canChangeConnectorText(connector: Connector, position: number): boolean { return this.requestOperation(new BeforeChangeConnectorTextRequestedEntity(this.apiController, connector, position)); } canApplyShapeTextChange(shape: Shape, textToApply: string): boolean { return this.requestOperation(new ChangeShapeTextRequestedEntity(this.apiController, shape, textToApply)); } canApplyConnectorTextChange(connector: Connector, position: number, textToApply: string): boolean { return this.requestOperation(new ChangeConnectorTextRequestedEntity(this.apiController, connector, position, textToApply)); } canResizeShapes(shapeInfo: IResizeShapeInfo[]): boolean { let allowed = true; shapeInfo.forEach((info) => { allowed = allowed && this.requestOperation(new ResizeShapeRequestedEntity(this.apiController, info.shape, info.oldSize, info.size)); }); return allowed; } canMoveShapes(shapeInfo: IMoveShapeInfo[]): boolean { let allowed = true; shapeInfo.forEach((info) => { allowed = allowed && this.requestOperation(new MoveShapeRequestedEntity(this.apiController, info.shape, info.oldPosition, info.position)); }); return allowed; } private requestOperation(entity: RequestedEntity): boolean { let allowed = true; if(!this.permissionsLockCount) { let cachedEntity; if(this.updateUICount > 0) this.cache.forEach(item => { if(item.equals(entity)) { cachedEntity = item; return; } }); if(cachedEntity) allowed = cachedEntity.allowed; else { this.requestOperationCore(entity); if(this.updateUICount > 0) this.cache.push(entity); allowed = entity.allowed; } if(this.updateUICount === 0 && this.storage.needStorePermissions()) { this.storage.storePermission(entity.storageKey, allowed); return this.storage.isStoredPermissionsGranted(); } } return allowed; } private requestOperationCore(entity: RequestedEntity) { entity.eventArgs.allowed = this.operationSettings[entity.settingsKey]; entity.eventArgs.updateUI = this.updateUICount > 0; if(entity.allowed) this.onRequestOperation.raise("notifyRequestOperation", entity.operation, entity.eventArgs); } lockPermissions(): void { this.permissionsLockCount++; } unlockPermissions(): void { this.permissionsLockCount--; } beginDeleteItems(items: DiagramItem[]): void { items.forEach(item => this.requestDeleteItems[item.key] = item); } endDeleteItems(): void { this.requestDeleteItems = {}; } beginUpdateUI(): void { this.updateUICount++; } endUpdateUI(): void { this.updateUICount--; } addInteractingItem(item: DiagramItem, operation?: DiagramModelOperation): void { this.storage.addInteractingItem(item, operation); } getInteractingItem(item: DiagramItem, operation?: DiagramModelOperation): DiagramItem { return this.storage.getInteractingItem(item, operation); } getInteractingItemCount(): number { return this.storage.getInteractingItemCount(); } clearInteractingItems(): void { this.storage.clearInteractingItems(); } beginStorePermissions(): void { this.storage.beginStorePermissions(); } endStorePermissions(): void { this.storage.endStorePermissions(); } isStoredPermissionsGranted(): boolean { return this.permissionsLockCount > 0 || this.storage.isStoredPermissionsGranted(); } } export interface IPermissionsProvider { lockPermissions(): void; unlockPermissions(): void; beginDeleteItems(items: DiagramItem[]): void; endDeleteItems(): void; beginUpdateUI(): void; endUpdateUI(): void; canDeleteItems(items: DiagramItem[]): boolean; canAddItems(items: DiagramItem[]): boolean; canAddShapeFromToolbox(itemType: string): boolean; canChangeConnection(connector: Connector, item: DiagramItem, oldItem: DiagramItem, position: ConnectorPosition, connectionPointIndex: number): boolean; canChangeConnectorPoints(connector: Connector, oldPoints: Point[], points: Point[]): boolean; canChangeShapeText(shape: Shape): boolean; canChangeConnectorText(connector: Connector, position: number): boolean; canApplyShapeTextChange(shape: Shape, textToApply: string): boolean; canApplyConnectorTextChange(connector: Connector, position: number, textToApply: string): boolean; canResizeShapes(shapeInfo: IResizeShapeInfo[]): boolean; canMoveShapes(shapeInfo: IMoveShapeInfo[]): boolean; addInteractingItem(item: DiagramItem, operation?: DiagramModelOperation); getInteractingItem(item: DiagramItem, operation?: DiagramModelOperation): DiagramItem; getInteractingItemCount(): number; clearInteractingItems(); beginStorePermissions(): void; endStorePermissions(): void; isStoredPermissionsGranted(): boolean; } export interface IPermissionRequestListener { notifyRequestOperation(operation: DiagramModelOperation, args: RequestOperationEventArgs); } export type RequestOperationEventArgs = DeleteShapeEventArgs | DeleteConnectorEventArgs | AddShapeFromToolboxEventArgs | AddShapeEventArgs | ChangeConnectionEventArgs | ChangeConnectorPointsEventArgs | BeforeChangeShapeTextEventArgs | BeforeChangeShapeTextEventArgs | ChangeShapeTextEventArgs;