LayoutVertical.cc 5.04 KB
/*
 * LayoutVertical.hh
 *
 *  Created on: Sep, 2, 2014
 *      Author: AKKA
 */


#include "LayoutVertical.hh"
#include "PlotLogger.hh"

namespace plot {

/**
 * @Brief Add a panel characterized by it's constraint to the layout
 */

void LayoutVertical::addPanel (PanelConstraint panelConstraint, double preferedWidth/*=-1*/, double preferedHeight/*=-1*/) {
	double width=0, height=0;

	switch (panelConstraint) {
	case PanelConstraint::MaxWidth:

		width = 1.0;

		if (preferedHeight != -1)
			height = preferedHeight;
		else
			height = _requestPanelHeight;

		break;

	case PanelConstraint::Square:

		if (preferedWidth != -1)
			width = preferedWidth;
		else
			width = _requestPanelHeight / _xyRatio;

		if (preferedHeight != -1)
			height = preferedHeight;
		else
			height = _requestPanelHeight;

		break;
	default:
		// TODO lever exception ici ???
		break;
	}

	_panelsInfo.push_back (new PanelInfo (panelConstraint, preferedWidth, preferedHeight, width, height));
}

/**
 * @Brief Reset Layout internal parameters and compute optimized parameters
 * like _panelHeight, _panelWidth, _panelYSpacing...
 */

void LayoutVertical::reset (void) {
	// Reset current panels and position
	_curPanel	= 0;
	_curYPosition = 0;
	_maxWidthConstraintFound = false;

	// Compute general data for the layout depending on
	// - the number of panel
	// - their constraint
	_panelYSpacing	= _requestPanelSpacing;

	double layoutWidth, layoutHeight;
	computeLayoutSize (layoutWidth, layoutHeight);

	// Normalize width & height if more than 1
	if (layoutHeight > 1) {
		for (auto panelInfo : _panelsInfo) {
			panelInfo->_preferedHeight /= layoutHeight;
			panelInfo->_height /= layoutHeight;
		}
		_panelYSpacing /= layoutHeight;
	}

	if (layoutWidth > 1) {
		for (auto panelInfo : _panelsInfo) {
			if (panelInfo->_constraint != PanelConstraint::MaxWidth) {
				panelInfo->_preferedWidth /= layoutWidth;
				panelInfo->_width /= layoutWidth;
			}
		}
	}

	// Expand _requestPanelHeight if necessary and asked
	if ((layoutHeight < 1) && (layoutWidth <= 1) && (_autoExpand == true)) {
		expand (1.01);
		expand (1.001);
		expand (1.0001);
	}
}

/**
 * @Brief Increase panelHeight by step until layoutHeight reach (but not over step) 1.0
 */

void LayoutVertical::expand (double ratio) {
	double layoutWidth, layoutHeight;
	do
	{
		// Increase panelHeight by step and keep the same ratio for panelSpacing
		_panelYSpacing	*= ratio;

		for (auto panelInfo : _panelsInfo) {
			panelInfo->_height *= ratio;
			if (panelInfo->_constraint != PanelConstraint::MaxWidth) {
				if (panelInfo->_preferedWidth != -1) {
					panelInfo->_width = panelInfo->_preferedWidth;
				} else {
					panelInfo->_width *= ratio;
				}
			}
		}
		computeLayoutSize (layoutWidth, layoutHeight);
	} while ((layoutHeight < 1.0) && (layoutWidth <= 1.0));

	// Restore last valid value for panelHeight and panelSpacing
	_panelYSpacing	/= ratio;

	for (auto panelInfo : _panelsInfo) {
		panelInfo->_height /= ratio;
		if (panelInfo->_constraint != PanelConstraint::MaxWidth) {
			if (panelInfo->_preferedWidth == -1) {
				panelInfo->_width /= ratio;
			}
		}
	}
	computeLayoutSize (layoutWidth, layoutHeight);
}

void LayoutVertical::computeLayoutSize (double &layoutWidth, double &layoutHeight) {
	layoutWidth = 0;
	layoutHeight = 0;
	_firstPanelHeightDelta = 0;
	bool maxWidthConstraintFound = false;

	for (auto panelInfo : _panelsInfo) {
		layoutHeight += (panelInfo->_height + _panelYSpacing);
		if (panelInfo->_width > layoutWidth)
			layoutWidth = panelInfo->_width;

		if ((maxWidthConstraintFound == false) &&
			(panelInfo->_constraint == PanelConstraint::MaxWidth)) {
			maxWidthConstraintFound = true;
			_firstPanelHeightDelta = (_firstPanelHeightFactor-1.0) * panelInfo->_height;
			layoutHeight += _firstPanelHeightDelta;
		}
	}

	// Remove one spacing if more than 1 panel
	if (_panelsInfo.size () > 1)
		layoutHeight -= _panelYSpacing;
}

Bounds & LayoutVertical::getNextBounds (PanelConstraint panelConstraint) {

	PanelInfo *panelInfo = _panelsInfo.at(_curPanel);

	// Computes panels position on the layout depending on their constraints
	switch (panelConstraint) {

	case PanelConstraint::MaxWidth:
		_computedPanelBounds._x = 0;
		_computedPanelBounds._y = _curYPosition;
		_computedPanelBounds._width = 1.0;
		_computedPanelBounds._height = panelInfo->_height;

		// The first MaxWidth panel can have an extra panel height
		if (_maxWidthConstraintFound == false) {
			_maxWidthConstraintFound = true;
			_computedPanelBounds._height	+= _firstPanelHeightDelta;
			_curYPosition 					+= _firstPanelHeightDelta;
		}

		_curPanel++;
		_curYPosition += (panelInfo->_height + _panelYSpacing);
		break;

	case PanelConstraint::Square:
		// Compute x position of the SquarePanel on the line (centered)
		_computedPanelBounds._x = 0.5 - (panelInfo->_width / 2.0);
		_computedPanelBounds._y = _curYPosition;

		_computedPanelBounds._width = panelInfo->_width;
		_computedPanelBounds._height = panelInfo->_height;

		_curPanel++;
		_curYPosition += (panelInfo->_height + _panelYSpacing);
		break;

	default:
		// TODO lever exception ici ???
		break;
	}

	return _computedPanelBounds;
}

}