Panel.cc 9.54 KB
/*
 * Panel.cc
 *
 *  Created on: 28 oct. 2013
 *      Author: CS
 */

#include "Panel.hh"
#include "DefaultPlotConfiguration.hh"
#include "ColormapManager.hh"
#include "Label.hh"
#include "PlotLogger.hh"


namespace plot {

const float Panel::TEXT_FACTOR = 5.1;

const float Panel::LINE_SPACE_TITLE = 0.4;

int Panel::PANEL_COUNTER = 0;

Panel::Panel() :
		_id(++PANEL_COUNTER),
		_resolution(0),
		_font(Font("", 0)),
		_title(Font("", 0)),
		_updateTitleOnNextInterval(false),
		_bounds(Bounds()),
		_backgroundColor(Color()),
		_titleAlign(PlotCommon::Align::CENTER),
		_titlePosition(PlotCommon::Position::POS_TOP),
		_drawn(false),
		_page(),
		_preferedWidth(-1),
		_preferedHeight(-1),
		_leftMargin(-1),
		_rightMargin(-1),
		_topMargin(-1),
		_bottomMargin(-1),
		_paramsLegendProperties(),
		_textLegendPropertiesList(),
		_titlePositionUnits(0)
{
}

Panel::Panel(DefaultPlotConfiguration& defaults) :
		_id(++PANEL_COUNTER),
		_resolution(defaults._defaultPanel._resolution),
		_font(defaults._defaultPanel._font),
		_title(defaults._defaultPanel._font),
		_updateTitleOnNextInterval(false),
		_bounds(Bounds()),
		_backgroundColor(defaults._defaultPanel._backgroundColor),
		_titleAlign(defaults._defaultPanel._titleAlign),
		_titlePosition(defaults._defaultPanel._titlePosition),
		_drawn(false),
		_page(),
		_preferedWidth(defaults._defaultPanel._preferedWidth),
		_preferedHeight(defaults._defaultPanel._preferedHeight),
		_leftMargin(defaults._defaultPanel._leftMargin),
		_rightMargin(defaults._defaultPanel._rightMargin),
		_topMargin(defaults._defaultPanel._topMargin),
		_bottomMargin(defaults._defaultPanel._bottomMargin),
		_textLegendPropertiesList(defaults._defaultPanel._textLegendPropertiesList),
		_titlePositionUnits(defaults._defaultPanel._titlePositionUnits)
{
}

Panel::Panel(Page* page) :
		_id(++PANEL_COUNTER),
		_resolution(DefaultPlotConfiguration::getInstance()._defaultPanel._resolution),
		_font(Font(
				DefaultPlotConfiguration::getInstance()._defaultPanel._font._name.empty() ?
						page->_font._name :
						DefaultPlotConfiguration::getInstance()._defaultPanel._font._name,
				DefaultPlotConfiguration::getInstance()._defaultPanel._font._size
						!= 0 ?
						DefaultPlotConfiguration::getInstance()._defaultPanel._font._size :
						page->_font._size)),
		_title(_font),
		_updateTitleOnNextInterval(false),
		_bounds(Bounds()),
		_backgroundColor(DefaultPlotConfiguration::getInstance()._defaultPanel._backgroundColor),
		_titleAlign(DefaultPlotConfiguration::getInstance()._defaultPanel._titleAlign),
		_titlePosition(DefaultPlotConfiguration::getInstance()._defaultPanel._titlePosition),
		_drawn(false),
		_page(page),
		_preferedWidth(DefaultPlotConfiguration::getInstance()._defaultPanel._preferedWidth),
		_preferedHeight(DefaultPlotConfiguration::getInstance()._defaultPanel._preferedHeight),
		_leftMargin(DefaultPlotConfiguration::getInstance()._defaultPanel._leftMargin),
		_rightMargin(DefaultPlotConfiguration::getInstance()._defaultPanel._rightMargin),
		_topMargin(DefaultPlotConfiguration::getInstance()._defaultPanel._topMargin),
		_bottomMargin(DefaultPlotConfiguration::getInstance()._defaultPanel._bottomMargin),
		_textLegendPropertiesList(DefaultPlotConfiguration::getInstance()._defaultPanel._textLegendPropertiesList),
		_titlePositionUnits(DefaultPlotConfiguration::getInstance()._defaultPanel._titlePositionUnits)
{
}

Panel::~Panel() {

}

void Panel::draw(std::shared_ptr<plstream>& pls) {
	// Compute panel coordinate in the page
	Bounds lBounds = getCoordinateInPlPage(pls.get(), _bounds, _page);

	// Specify viewport for the panel
	pls->vpor(lBounds._x, lBounds._x + lBounds._width,
			  lBounds._y, lBounds._y + lBounds._height);

	// Set window size.
	pls->wind(lBounds._x, lBounds._x + lBounds._width,
			  lBounds._y, lBounds._y + lBounds._height);

	if (_drawn)
		//panel is already drawn => no draw background and title
		return;

	fillBackground(pls, lBounds);

	// write title with dedicated position and align
	pls->col0(0);

	Color lInitialColor = changeColor(pls, _title._color, _page->_mode);

	pls->sfont(getPlFontFamily(_title._font.isSet() ? _title._font : _font),
				   (_title._font.isSet() ? getPlFontStyle(_title._style) : _font._style),
				   (_title._font.isSet() ? getPlFontWeight(_title._style) : _font._weight));
	if (_title._font.isSet())
		pls->schr(getPlFontDef(_title._font), getPlFontScaleFactor(_title._font));
	else
		pls->schr(getPlFontDef(_font), getPlFontScaleFactor(_font));

	// Draw panel title depending on page title existence

	LabelRowInfo titleRows(Label::getRowNumber(_title));

	float lRowDisp = getTitlePositionUnits();
	// Draw each line of title
	for (auto row: *(titleRows.get())) {
		pls->mtex(	getPlSide(_titlePosition).c_str(),
					lRowDisp,
					getPlPos(_titleAlign),
					getPlJust(_titleAlign),
					row.c_str());

		// 1 is for full character and then let space between two line.
		lRowDisp -= (1 + LINE_SPACE_TITLE);
	}

	// Restore initial color.
	restoreColor(pls, lInitialColor, _page->_mode);

	_drawn = true;
}

/**
 * @brief Write panel context
 */
void Panel::writeContext(std::shared_ptr<plstream>& pls, ContextFileWriter& writer) {
	Bounds lBounds = getCoordinateInPlPage(pls.get(), _bounds, _page);

	writer.startElement("panel");
	writer.addAttribute("x", std::to_string(lBounds._x*std::get<0>(_page->getSize())).c_str());
	writer.addAttribute("y", std::to_string(lBounds._y*std::get<1>(_page->getSize())).c_str());
	writer.addAttribute("width", std::to_string(lBounds._width*std::get<0>(_page->getSize())).c_str());
	writer.addAttribute("height", std::to_string(lBounds._height*std::get<1>(_page->getSize())).c_str());
	writer.endElement();
}

void Panel::fillBackground(std::shared_ptr<plstream>& pls,
		Bounds& pBounds) const {
	// If color map index is not equal to 0, need to change cmap0.
	if (_backgroundColor._colorMapIndex != -1) {
		std::string lFilePath = ColormapManager::getInstance().get(_page->_mode,
				_backgroundColor._colorMapIndex);
		pls->spal0(lFilePath.c_str());
	}

	PLINT lInitialRed = -1, lInitialGreen = -1, lInitialBlue = -1;
	// if color index is equal to 0 choose the first color in cmap 0
	if (_backgroundColor._colorIndex != -1) {
		pls->col0(_backgroundColor._colorIndex);
	} else if (_backgroundColor._red != -1 && _backgroundColor._green != -1
			&& _backgroundColor._blue != -1) {
		// Store initial color in first index.
		pls->gcol0(0, lInitialRed, lInitialGreen, lInitialBlue);
		pls->scol0(0, _backgroundColor._red, _backgroundColor._green,
				_backgroundColor._blue);
		pls->col0(0);
	} else {
		// chose first color in cmap0.
		pls->col0(0);
	}

	// Fill background.
	PLFLT px[] = { pBounds._x, pBounds._x, pBounds._x + pBounds._width,
			pBounds._x + pBounds._width };
	PLFLT py[] = { pBounds._y, pBounds._y + pBounds._height, pBounds._y
			+ pBounds._height, pBounds._y };
	pls->fill(4, px, py);

	// Restore initial color in first index.
	if (lInitialRed != -1 && lInitialGreen != -1 && lInitialBlue != -1) {
		pls->scol0(0, lInitialRed, lInitialGreen, lInitialBlue);
	} else if (_backgroundColor._colorMapIndex != -1) {
		// Restore default cmap0 (default colormap for cmap0 is the first index).
		std::string lFilePath = ColormapManager::getInstance().get(_page->_mode,
				0);
		pls->spal0(lFilePath.c_str());
	}
}

Bounds Panel::getCoordinateInPlPage(plstream* pls, const Bounds& pBounds, Page* pPage) {
	Bounds lBounds;

	// Get font scale for title and copyright of page
	double lFontFactorPage = getPlFontScaleFactor(pPage->_font);

	// Get default char height of plplot
	PLFLT lDefaultCharHeight, lCurrentCharHeight;
	pls->gchr(lDefaultCharHeight, lCurrentCharHeight);

	// Calculate space to have title and copyright visible
	// Get char height in normalized coordinate.
	double lMaxCharHeight = TEXT_FACTOR * (lDefaultCharHeight * lFontFactorPage)
			/ (std::get < 1 > (pPage->getSize()));

	// Calculate transformation to get new point of reference (AMDA Page reference)
	double lXOffset = pPage->_xMargin;

	// Substract left and right margin
	double lXPageRatio = (1 - (2 * lXOffset));

	double lYOffset = pPage->_yMargin;

	// Substract top and bottom margin and space for copyright and title.
	double lYPageRatio = (1 - (2 * lYOffset) - (2 * lMaxCharHeight));

	// Add char height to have copyright visible
	lYOffset += lMaxCharHeight;

	// Calculate panel bounds in AMDA page.
	double lXMax;
	double lYMax;

	lBounds._x = (pBounds._x * lXPageRatio) + lXOffset;
	lBounds._y = (pBounds._y * lYPageRatio) + lYOffset;
	lXMax = ((pBounds._x + pBounds._width) * lXPageRatio) + lXOffset;
	lYMax = ((pBounds._y + pBounds._height) * lYPageRatio) + lYOffset;

	lBounds._width = lXMax - lBounds._x;
	lBounds._height = lYMax - lBounds._y;

	return lBounds;
}

float Panel::getTitlePositionUnits (void) {
	_titlePositionUnits = _page->_title._text.empty() ? -1. : -2.;
	return _titlePositionUnits;
}

std::ostream& operator <<(std::ostream& out, Bounds& bounds) {
	out << "[BOUNDS]" << std::endl;
	out << "bounds.x=" << bounds._x << std::endl;
	out << "bounds.y=" << bounds._y << std::endl;
	out << "bounds.width=" << bounds._width << std::endl;
	out << "bounds.height=" << bounds._height << std::endl;

	return out;
}

std::ostream& operator <<(std::ostream& out, Panel& panel) {
	out << "[PANEL]" << std::endl;
	out << "panel.resolution=" << panel._resolution << std::endl;
	out << "panel.title=" << panel._title._text << std::endl;
	out << "panel.title.align=" << panel._titleAlign << std::endl;
	out << "panel.title.position=" << panel._titlePosition << std::endl;
	out << panel._bounds << panel._backgroundColor << panel._font;
	for (auto axe : panel._axes) {
		if (axe.second != nullptr)
			axe.second.get()->dump(out);
	}
	return out;
}

} /* namespace plot */