LayoutAuto.cc 6.38 KB
/*
 * LayoutAuto.hh
 *
 *  Created on: Sep, 2, 2014
 *      Author: AKKA
 */


#include "LayoutAuto.hh"
#include "PlotLogger.hh"
#include "DecoratorPlot.hh"

#include <boost/range/adaptor/reversed.hpp>

namespace plot {

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

void LayoutAuto::addPanel (PanelConstraint panelConstraint, double /*preferedWidth=-1*/, double /*preferedHeight=-1*/) {
	switch (panelConstraint) {
	case PanelConstraint::MaxWidth:
		_nbMaxWidthPanel++;
		break;
	case PanelConstraint::Square:
		_nbSquarePanel++;
		break;
	default:
		// TODO lever exception ici ???
		break;
	}
}

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

void LayoutAuto::reset (void) {
	// Reset current panels
	_curMaxWidthPanel	= 0;
	_curSquarePanel		= 0;
	_curSquarePanelLine = 0;

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

	double layoutHeight = computeLayoutHeight ();

	// Shrink _requestPanelHeight if necessary
	if (layoutHeight > 1) {
		shrink (0.01);
		expand (0.001);
	}

	// Expand _requestPanelHeight if necessary and asked
	else if ((layoutHeight < 1) && (_autoExpand == true)) {
		expand (0.01);
		expand (0.001);
		expand (0.0001);
	}
}

/**
 * @Brief Decrease panelHeight by step while layoutHeight is more than 1.0
 */

void LayoutAuto::shrink (double step) {
	double layoutHeight;
	do
	{
		// Decrease panelHeight by step and keep the same ratio for panelSpacing
		_panelHeight 	-= step;
		_panelYSpacing	= _requestPanelSpacing * (_panelHeight / _requestPanelHeight);
		layoutHeight = computeLayoutHeight ();
	} while (layoutHeight > 1.0);
}

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

void LayoutAuto::expand (double step) {
	double layoutHeight;
	do
	{
		// Increase panelHeight by step and keep the same ratio for panelSpacing
		_panelHeight 	+= step;
		_panelYSpacing	= _requestPanelSpacing * (_panelHeight / _requestPanelHeight);
		layoutHeight = computeLayoutHeight ();
	} while (layoutHeight < 1.0);

	// Restore last valid value for panelHeight and panelSpacing
	_panelHeight 	-= step;
	_panelYSpacing	= _requestPanelSpacing * (_panelHeight / _requestPanelHeight);
	computeLayoutHeight ();
}

double LayoutAuto::computeLayoutHeight (void) {
	double layoutHeight = 0;
	_nbLineForSquarePanel = 0;
	_firstPanelHeightDelta = 0;

	_panelWidth 	= _panelHeight / _xyRatio;
	_panelXSpacing	= _panelYSpacing / _xyRatio;

	// Computes _nbMaxSquarePanelByLine and nbLineForSquarePanel for the layout
	// then computes panelHeight
	_nbMaxSquarePanelByLine = (int) ((1.0 + _panelXSpacing) / (_panelWidth + _panelXSpacing));

	_nbLineForSquarePanel = _nbSquarePanel / _nbMaxSquarePanelByLine;
	if ((_nbSquarePanel % _nbMaxSquarePanelByLine) != 0)
		_nbLineForSquarePanel++;

	// Computes height for MaxWidth Panel
	if (_nbMaxWidthPanel > 0) {
		layoutHeight += _nbMaxWidthPanel * _panelHeight + (_nbMaxWidthPanel - 1) * _panelYSpacing;
		_firstPanelHeightDelta = (_firstPanelHeightFactor-1.0) * _panelHeight;
		layoutHeight += _firstPanelHeightDelta;
	}

	// Computes height for Square Panel
	if (_nbSquarePanel > 0)
		layoutHeight += _nbLineForSquarePanel * _panelHeight + (_nbLineForSquarePanel - 1) * _panelYSpacing;

	// Add space between MaxWidth and Square ?
	if ((_nbMaxWidthPanel > 0) && (_nbSquarePanel > 0))
		layoutHeight += _panelYSpacing;

//	LOG4CXX_DEBUG(gLogger,"Layout::computeLayoutHeight _nbMaxPanelSquareByLine = " << _nbMaxSquarePanelByLine);
//	LOG4CXX_DEBUG(gLogger,"Layout::computeLayoutHeight _nbLineForSquarePanel = " << _nbLineForSquarePanel);
//	LOG4CXX_DEBUG(gLogger,"Layout::computeLayoutHeight layoutHeight = " << layoutHeight);
	return layoutHeight;
}

Bounds & LayoutAuto::getNextBounds (PanelConstraint panelConstraint) {
	int nbSquarePanelOnLine;
	double lastSquarePanelXPosition;

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

	case PanelConstraint::MaxWidth:
		_computedPanelBounds._x = 0;
		_computedPanelBounds._y = _curMaxWidthPanel *(_panelHeight + _panelYSpacing);
		_computedPanelBounds._width = 1.0;
		_computedPanelBounds._height = _panelHeight;

		// The first MaxWidth panel can have an extra panel height
		if (_curMaxWidthPanel != 0) {
			_computedPanelBounds._y 		+= _firstPanelHeightDelta;
		}
		if (_curMaxWidthPanel == 0) {
			_computedPanelBounds._height	+= _firstPanelHeightDelta;
		}

		_curMaxWidthPanel++;
		break;

	case PanelConstraint::Square:
		// Compute number of square panel on the current line
		// Are we on the last PanelSquareLine ?
		if (_curSquarePanelLine == (_nbLineForSquarePanel - 1))
			nbSquarePanelOnLine = _nbSquarePanel - (_curSquarePanelLine * _nbMaxSquarePanelByLine);
		else
			nbSquarePanelOnLine = _nbMaxSquarePanelByLine;

		// Compute x position of the last SquarePanel on the line (centered)
		lastSquarePanelXPosition = 0.5
				+ ((((nbSquarePanelOnLine) * _panelWidth) + ((nbSquarePanelOnLine-1) * _panelXSpacing)) / 2.0) - _panelWidth;

		_computedPanelBounds._x = lastSquarePanelXPosition
								- (_curSquarePanel % _nbMaxSquarePanelByLine) * (_panelWidth + _panelXSpacing);;
		_computedPanelBounds._y = (_nbMaxWidthPanel + _curSquarePanelLine) *(_panelHeight + _panelYSpacing);
		if (_nbMaxWidthPanel != 0) {
			_computedPanelBounds._y += _firstPanelHeightDelta;
		}

		_computedPanelBounds._width = _panelWidth;
		_computedPanelBounds._height = _panelHeight;

		_curSquarePanel++;

		// Next line for square panel
		if ((_curSquarePanel % _nbMaxSquarePanelByLine) == 0)
			_curSquarePanelLine++;

		break;

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

	return _computedPanelBounds;
}

void LayoutAuto::computePanelsPosition (std::vector<boost::shared_ptr<PanelPlotOutput>> _plots,  std::map<std::string, ParameterData> * /*parameterValues*/) {
	// Add panels constraint to the layout
	for (auto plot : boost::adaptors::reverse(_plots)) {
		if (!plot->isStandalone())
			continue;

		this->addPanel ( plot->getLayoutConstraint(),
							plot->_panel->_preferedWidth,
							plot->_panel->_preferedHeight);
	}

	// Reset layout
	this->reset();


	for (auto plot : boost::adaptors::reverse(_plots)) {
		if (!plot->isStandalone())
			continue;

		plot->_panel->_bounds = this->getNextBounds (plot->getLayoutConstraint());
	}
}

}