import { LayoutPanelComponent } from './panels/layout-panel.component'; import { Injector, ContentChildren, ViewEncapsulation, Output, EventEmitter, Inject, forwardRef, NgZone } from '@angular/core'; /* * @Author: 疯狂秀才(lucas huang) * @Date: 2018-11-24 15:58:04 * @LastEditors: 疯狂秀才(Lucas Huang) * @LastEditTime: 2019-04-08 19:02:25 * @Company: Inspur * @Version: v0.0.1 */ import { Component, OnInit, Input, QueryList, ViewChildren, HostBinding, ElementRef, Renderer2, Directive, AfterContentInit, ViewChild } from '@angular/core'; @Component({ selector: 'farrisui-layout,farris-layout,layout', templateUrl: 'layout.component.html', styles: [ ` :host.layout-fill {position: absolute; top: 0; right: 0;bottom: 0;left: 0;} ` ], encapsulation: ViewEncapsulation.Emulated }) export class LayoutComponent implements OnInit, AfterContentInit { @Input() width: number; @Input() height: number; @Input() showBorder = true; // h: 水平排列; v: 垂直排列 @Input() direction: 'h' | 'v' = 'h'; @Input() fill = false; @HostBinding('class') myclass = 'd-flex'; panels: LayoutPanelComponent[] = []; private ngZone: NgZone; constructor(private el: ElementRef, private render2: Renderer2, private injector: Injector) { this.ngZone = this.injector.get(NgZone); } ngOnInit() { this.init(); } ngAfterContentInit() { this.checkPanels(); this.panels.forEach(p => { if (p.split) { let margin = ''; switch (p.region) { case 'north': margin = 'marginTop'; break; case 'south': margin = 'marginBottom'; break; case 'west': margin = 'marginLeft'; break; case 'east': margin = 'marginRight'; break; } this.render2.setStyle(this.getPanel('center').el.nativeElement, margin, '5px'); } }); this.ngZone.runOutsideAngular(() => { setTimeout(() => this.setPanelMaxSize()); }); } private init() { if (this.direction === 'h') { this.myclass += ' flex-row'; } else { this.myclass += ' flex-column'; } if (this.fill) { if (this.isInLayoutPanel()) { this.myclass += ' flex-fill'; this.render2.addClass(this.el.nativeElement.parentElement, 'd-flex'); } else { this.myclass += ' layout-fill'; } } else { if (this.width) { this.render2.setStyle(this.el.nativeElement, 'width', this.width + 'px'); } if (this.height) { this.render2.setStyle(this.el.nativeElement, 'height', this.height + 'px'); } } } private getLayoutSize() { const size = { width: this.el.nativeElement.clientWidth, height: this.el.nativeElement.clientHeight }; return size; } setPanelMaxSize() { const layoutSize = this.getLayoutSize(); this.panels.forEach(p => { if (p.region !== 'center') { if (p.region === 'west' && layoutSize.width) { const east = this.getPanel('east'); if (!east) { p.maxWidth = layoutSize.width - 100; } else { p.maxWidth = layoutSize.width - east.width - 100; } } if (p.region === 'east' && layoutSize.width) { const west = this.getPanel('west'); if (!west) { p.maxWidth = layoutSize.width - 100; } else { p.maxWidth = layoutSize.width - west.width - 100; } } if (p.region === 'north' && layoutSize.height) { const south = this.getPanel('south'); if (!south) { p.maxHeight = layoutSize.height - 100; } else { p.maxHeight = layoutSize.height - south.height - 100; } } if (p.region === 'south' && layoutSize.height) { const north = this.getPanel('north'); if (!north) { p.maxHeight = layoutSize.height - 100; } else { p.maxHeight = layoutSize.height - north.height - 100; } } } }); } getPanel(region: string) { return this.panels.find(p => p.region === region); } private checkPanels() { if (this.panels && this.panels.length) { const regions = this.panels.map(p => p.region); if (this.unique(regions).length === regions.length) { if (this.direction === 'h') { if (regions.find(r => r === 'north' || r === 'south')) { throw new Error('水平方向排列时,只能包含 east 或者 west'); } } else { if (regions.find(r => r === 'west' || r === 'east')) { throw new Error('水平方向排列时,只能包含 north 或者 south'); } } return true; } else { throw new Error('layout 布局容器中具有重复的panel。'); } } return true; } private unique(arr: string[]) { const tmp = new Set(arr); return Array.from(tmp); } private isInLayoutPanel() { return !!this.el.nativeElement.parentElement.attributes['layout-panel']; } }