123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- import { Container } from "./container";
- import { ValueAndUnit } from "../valueAndUnit";
- import { Control } from "./control";
- import { Measure } from "../measure";
- /**
- * Class used to create a 2D grid container
- */
- export class Grid extends Container {
- private _rowDefinitions = new Array<ValueAndUnit>();
- private _columnDefinitions = new Array<ValueAndUnit>();
- private _cells: { [key: string]: Container } = {};
- private _childControls = new Array<Control>();
- /** Gets the list of children */
- public get children(): Control[] {
- return this._childControls;
- }
- /**
- * Adds a new row to the grid
- * @param height defines the height of the row (either in pixel or a value between 0 and 1)
- * @param isPixel defines if the height is expressed in pixel (or in percentage)
- * @returns the current grid
- */
- public addRowDefinition(height: number, isPixel = false): Grid {
- this._rowDefinitions.push(new ValueAndUnit(height, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE));
- this._markAsDirty();
- return this;
- }
- /**
- * Adds a new column to the grid
- * @param width defines the width of the column (either in pixel or a value between 0 and 1)
- * @param isPixel defines if the width is expressed in pixel (or in percentage)
- * @returns the current grid
- */
- public addColumnDefinition(width: number, isPixel = false): Grid {
- this._columnDefinitions.push(new ValueAndUnit(width, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE));
- this._markAsDirty();
- return this;
- }
- /**
- * Update a row definition
- * @param index defines the index of the row to update
- * @param height defines the height of the row (either in pixel or a value between 0 and 1)
- * @param isPixel defines if the weight is expressed in pixel (or in percentage)
- * @returns the current grid
- */
- public setRowDefinition(index: number, height: number, isPixel = false): Grid {
- if (index < 0 || index >= this._rowDefinitions.length) {
- return this;
- }
- this._rowDefinitions[index] = new ValueAndUnit(height, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE);
- this._markAsDirty();
- return this;
- }
- /**
- * Update a column definition
- * @param index defines the index of the column to update
- * @param width defines the width of the column (either in pixel or a value between 0 and 1)
- * @param isPixel defines if the width is expressed in pixel (or in percentage)
- * @returns the current grid
- */
- public setColumnDefinition(index: number, width: number, isPixel = false): Grid {
- if (index < 0 || index >= this._columnDefinitions.length) {
- return this;
- }
- this._columnDefinitions[index] = new ValueAndUnit(width, isPixel ? ValueAndUnit.UNITMODE_PIXEL : ValueAndUnit.UNITMODE_PERCENTAGE);
- this._markAsDirty();
- return this;
- }
- private _removeCell(cell: Container, key: string) {
- if (!cell) {
- return;
- }
- super.removeControl(cell);
- for (var control of cell.children) {
- let childIndex = this._childControls.indexOf(control);
- if (childIndex !== -1) {
- this._childControls.splice(childIndex, 1);
- }
- }
- delete this._cells[key];
- }
- private _offsetCell(previousKey: string, key: string) {
- if (!this._cells[key]) {
- return;
- }
- this._cells[previousKey] = this._cells[key];
- for (var control of this._cells[previousKey].children) {
- control._tag = previousKey;
- }
- delete this._cells[key];
- }
- /**
- * Remove a column definition at specified index
- * @param index defines the index of the column to remove
- * @returns the current grid
- */
- public removeColumnDefinition(index: number): Grid {
- if (index < 0 || index >= this._columnDefinitions.length) {
- return this;
- }
- for (var x = 0; x < this._rowDefinitions.length; x++) {
- let key = `${x}:${index}`;
- let cell = this._cells[key];
- this._removeCell(cell, key);
- }
- for (var x = 0; x < this._rowDefinitions.length; x++) {
- for (var y = index + 1; y < this._columnDefinitions.length; y++) {
- let previousKey = `${x}:${y - 1}`;
- let key = `${x}:${y}`;
- this._offsetCell(previousKey, key);
- }
- }
- this._columnDefinitions.splice(index, 1);
- this._markAsDirty();
- return this;
- }
- /**
- * Remove a row definition at specified index
- * @param index defines the index of the row to remove
- * @returns the current grid
- */
- public removeRowDefinition(index: number): Grid {
- if (index < 0 || index >= this._rowDefinitions.length) {
- return this;
- }
- for (var y = 0; y < this._columnDefinitions.length; y++) {
- let key = `${index}:${y}`;
- let cell = this._cells[key];
- this._removeCell(cell, key);
- }
- for (var y = 0; y < this._columnDefinitions.length; y++) {
- for (var x = index + 1; x < this._rowDefinitions.length; x++) {
- let previousKey = `${x - 1}:${y}`;
- let key = `${x}:${y}`;
- this._offsetCell(previousKey, key);
- }
- }
- this._rowDefinitions.splice(index, 1);
- this._markAsDirty();
- return this;
- }
- /**
- * Adds a new control to the current grid
- * @param control defines the control to add
- * @param row defines the row where to add the control (0 by default)
- * @param column defines the column where to add the control (0 by default)
- * @returns the current grid
- */
- public addControl(control: Control, row: number = 0, column: number = 0): Grid {
- if (this._rowDefinitions.length === 0) {
- // Add default row definition
- this.addRowDefinition(1, false);
- }
- if (this._columnDefinitions.length === 0) {
- // Add default column definition
- this.addColumnDefinition(1, false);
- }
- let x = Math.min(row, this._rowDefinitions.length - 1);
- let y = Math.min(column, this._columnDefinitions.length - 1);
- let key = `${x}:${y}`;
- let goodContainer = this._cells[key];
- if (!goodContainer) {
- goodContainer = new Container(key);
- this._cells[key] = goodContainer;
- goodContainer.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
- goodContainer.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
- super.addControl(goodContainer);
- }
- goodContainer.addControl(control);
- this._childControls.push(control);
- control._tag = key;
- this._markAsDirty();
- return this;
- }
- /**
- * Removes a control from the current container
- * @param control defines the control to remove
- * @returns the current container
- */
- public removeControl(control: Control): Container {
- var index = this._childControls.indexOf(control);
- if (index !== -1) {
- this._childControls.splice(index, 1);
- }
- let cell = this._cells[control._tag];
- if (cell) {
- cell.removeControl(control);
- }
- this._markAsDirty();
- return this;
- }
- /**
- * Creates a new Grid
- * @param name defines control name
- */
- constructor(public name?: string) {
- super(name);
- }
- protected _getTypeName(): string {
- return "Grid";
- }
- protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
- let widths = [];
- let heights = [];
- let lefts = [];
- let tops = [];
- let availableWidth = this._currentMeasure.width;
- let globalWidthPercentage = 0;
- let availableHeight = this._currentMeasure.height;
- let globalHeightPercentage = 0;
- // Heights
- let index = 0;
- for (var value of this._rowDefinitions) {
- if (value.isPixel) {
- let height = value.getValue(this._host);
- availableHeight -= height;
- heights[index] = height;
- } else {
- globalHeightPercentage += value.internalValue;
- }
- index++;
- }
- let top = 0;
- index = 0;
- for (var value of this._rowDefinitions) {
- tops.push(top);
- if (!value.isPixel) {
- let height = (value.internalValue / globalHeightPercentage) * availableHeight;
- top += height;
- heights[index] = height;
- } else {
- top += value.getValue(this._host);
- }
- index++;
- }
- // Widths
- index = 0;
- for (var value of this._columnDefinitions) {
- if (value.isPixel) {
- let width = value.getValue(this._host);
- availableWidth -= width;
- widths[index] = width;
- } else {
- globalWidthPercentage += value.internalValue;
- }
- index++;
- }
- let left = 0;
- index = 0;
- for (var value of this._columnDefinitions) {
- lefts.push(left);
- if (!value.isPixel) {
- let width = (value.internalValue / globalWidthPercentage) * availableWidth;
- left += width;
- widths[index] = width;
- } else {
- left += value.getValue(this._host);
- }
- index++;
- }
- // Setting child sizes
- for (var key in this._cells) {
- if (!this._cells.hasOwnProperty(key)) {
- continue;
- }
- let split = key.split(":");
- let x = parseInt(split[0]);
- let y = parseInt(split[1]);
- let cell = this._cells[key];
- cell.left = lefts[y] + "px";
- cell.top = tops[x] + "px";
- cell.width = widths[y] + "px";
- cell.height = heights[x] + "px";
- }
- super._additionalProcessing(parentMeasure, context);
- }
- /** Releases associated resources */
- public dispose() {
- super.dispose();
- for (var control of this._childControls) {
- control.dispose();
- }
- }
- }
|