import powerbiVisualsApi from "powerbi-visuals-api" ; import * as _ from "lodash" ; import IViewport = powerbiVisualsApi . IViewport ; import { IMargin } from "powerbi-visuals-utils-svgutils" ; export class VisualLayout { private marginValue : IMargin ; private viewportValue : IViewport ; private viewportInValue : IViewport ; private minViewportValue : IViewport ; private originalViewportValue : IViewport ; private previousOriginalViewportValue : IViewport ; public defaultMargin : IMargin ; public defaultViewport : IViewport ; constructor ( defaultViewport ? , defaultMargin ? ) { this . defaultViewport = defaultViewport || { width : 0 , height : 0 } ; this . defaultMargin = defaultMargin || { top : 0 , bottom : 0 , right : 0 , left : 0 } ; } public get viewport ( ) : IViewport { return this . viewportValue || ( this . viewportValue = this . defaultViewport ) ; } public get viewportCopy ( ) : IViewport { return _ . clone ( this . viewport ) ; } public get viewportIn ( ) : IViewport { return this . viewportInValue || this . viewport ; } public get minViewport ( ) : IViewport { return this . minViewportValue || { width : 0 , height : 0 } ; } public get margin ( ) : IMargin { return this . marginValue || ( this . marginValue = this . defaultMargin ) ; } public set minViewport ( value ) { this . setUpdateObject ( value , ( viewPoirt ) => this . minViewportValue = viewPoirt , VisualLayout . restrictToMinMax ) ; } public set viewport ( value ) { this . previousOriginalViewportValue = _ . clone ( this . originalViewportValue ) ; this . originalViewportValue = _ . clone ( value ) ; this . setUpdateObject ( value , ( viewport ) => this . viewportValue = viewport , ( viewport ) => VisualLayout . restrictToMinMax < IViewport > ( viewport , this . minViewport ) ) ; } public set margin ( value ) { this . setUpdateObject ( value , ( margin ) => this . marginValue = margin , VisualLayout . restrictToMinMax ) ; } public get viewportChanged ( ) : boolean { return ! ! this . originalViewportValue && ( ! this . previousOriginalViewportValue || this . previousOriginalViewportValue . height !== this . originalViewportValue . height || this . previousOriginalViewportValue . width !== this . originalViewportValue . width ) ; } public get viewportInIsZero ( ) : boolean { return this . viewportIn . width === 0 || this . viewportIn . height === 0 ; } public resetMargin ( ) { this . margin = this . defaultMargin ; } private update ( ) { this . viewportInValue = VisualLayout . restrictToMinMax ( { width : this . viewport . width - ( this . margin . left + this . margin . right ) , height : this . viewport . height - ( this . margin . top + this . margin . bottom ) } , this . minViewportValue ) ; } private setUpdateObject < T > ( object , setObjectFn , beforeUpdateFn ? ) { object = _ . clone ( object ) ; setObjectFn ( VisualLayout . createNotifyChangedObject ( object , ( ) => { if ( beforeUpdateFn ) { beforeUpdateFn ( object ) ; } this . update ( ) ; } ) ) ; if ( beforeUpdateFn ) { beforeUpdateFn ( object ) ; } this . update ( ) ; } private static createNotifyChangedObject < T > ( object , objectChanged ) { let result = < T > { } ; _ . keys ( object ) . forEach ( ( key ) => Object . defineProperty ( result , key , { get : ( ) => object [ key ] , set : ( value ) => { object [ key ] = value ; objectChanged ( object , key ) ; } , enumerable : true , configurable : true } ) ) ; return result ; } private static restrictToMinMax < T > ( value , minValue ? ) { _ . keys ( value ) . forEach ( ( key ) => value [ key ] = Math . max ( minValue && minValue [ key ] || 0 , value [ key ] ) ) ; return value ; } }