mediawiki-extensions-Visual.../modules/oojs-ui/layouts/OO.ui.GridLayout.js
Trevor Parscal d2dfb9ac4f Split oojs-ui from ve.ui
* Move and rename generic parts of ve.ui to OO.ui
* We now have a UI test suite because ve.Element (outside ve.ui)
  is now part of oojs-ui, so it needs a test suite.
* Added to the MW test run (just like we do for unicodejs).
* Updated csslint config (also added ve-mw and syntaxhighlight
  which were missing).

oojs-ui still depends on the TriggerRegistry in VE, this is addressed
in a follow-up commit.

Change-Id: Iec147155c1ddf20b73a4d15d87b8742207032312
2013-10-28 22:40:08 -07:00

171 lines
3.6 KiB
JavaScript

/*!
* ObjectOriented UserInterface GridLayout class.
*
* @copyright 2011-2013 OOJS Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Layout made of proportionally sized columns and rows.
*
* @class
* @extends OO.ui.Layout
*
* @constructor
* @param {OO.ui.PanelLayout[]} panels Panels in the grid
* @param {Object} [config] Configuration options
* @cfg {number[]} [widths] Widths of columns as ratios
* @cfg {number[]} [heights] Heights of columns as ratios
*/
OO.ui.GridLayout = function OoUiGridLayout( panels, config ) {
var i, len, widths;
// Config initialization
config = config || {};
// Parent constructor
OO.ui.Layout.call( this, config );
// Properties
this.panels = [];
this.widths = [];
this.heights = [];
// Initialization
this.$.addClass( 'oo-ui-gridLayout' );
for ( i = 0, len = panels.length; i < len; i++ ) {
this.panels.push( panels[i] );
this.$.append( panels[i].$ );
}
if ( config.widths || config.heights ) {
this.layout( config.widths || [1], config.heights || [1] );
} else {
// Arrange in columns by default
widths = [];
for ( i = 0, len = this.panels.length; i < len; i++ ) {
widths[i] = 1;
}
this.layout( widths, [1] );
}
};
/* Inheritance */
OO.inheritClass( OO.ui.GridLayout, OO.ui.Layout );
/* Events */
/**
* @event layout
*/
/**
* @event update
*/
/* Static Properties */
OO.ui.GridLayout.static.tagName = 'div';
/* Methods */
/**
* Set grid dimensions.
*
* @method
* @param {number[]} widths Widths of columns as ratios
* @param {number[]} heights Heights of rows as ratios
* @fires layout
* @throws {Error} If grid is not large enough to fit all panels
*/
OO.ui.GridLayout.prototype.layout = function ( widths, heights ) {
var x, y,
xd = 0,
yd = 0,
cols = widths.length,
rows = heights.length;
// Verify grid is big enough to fit panels
if ( cols * rows < this.panels.length ) {
throw new Error( 'Grid is not large enough to fit ' + this.panels.length + 'panels' );
}
// Sum up denominators
for ( x = 0; x < cols; x++ ) {
xd += widths[x];
}
for ( y = 0; y < rows; y++ ) {
yd += heights[y];
}
// Store factors
this.widths = [];
this.heights = [];
for ( x = 0; x < cols; x++ ) {
this.widths[x] = widths[x] / xd;
}
for ( y = 0; y < rows; y++ ) {
this.heights[y] = heights[y] / yd;
}
// Synchronize view
this.update();
this.emit( 'layout' );
};
/**
* Update panel positions and sizes.
*
* @method
* @fires update
*/
OO.ui.GridLayout.prototype.update = function () {
var x, y, panel,
i = 0,
left = 0,
top = 0,
dimensions,
width = 0,
height = 0,
cols = this.widths.length,
rows = this.heights.length;
for ( y = 0; y < rows; y++ ) {
for ( x = 0; x < cols; x++ ) {
panel = this.panels[i];
width = this.widths[x];
height = this.heights[y];
dimensions = {
'width': Math.round( width * 100 ) + '%',
'height': Math.round( height * 100 ) + '%',
'top': Math.round( top * 100 ) + '%'
};
// If RTL, reverse:
if ( this.$$.frame.dir === 'rtl' ) {
dimensions.right = Math.round( left * 100 ) + '%';
} else {
dimensions.left = Math.round( left * 100 ) + '%';
}
panel.$.css( dimensions );
i++;
left += width;
}
top += height;
left = 0;
}
this.emit( 'update' );
};
/**
* Get a panel at a given position.
*
* The x and y position is affected by the current grid layout.
*
* @method
* @param {number} x Horizontal position
* @param {number} y Vertical position
* @returns {OO.ui.PanelLayout} The panel at the given postion
*/
OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
return this.panels[( x * this.widths.length ) + y];
};