Panel.cc 11.2 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"
#include "PlPlotUtil.hh"


namespace plot {

//Auto id set to a negative number to preserve id defined in request
int Panel::PANEL_COUNTER = -1;

Panel::Panel() :
		_id(--PANEL_COUNTER),
		_index(-1),
		_resolution(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(),
		_font(Font("", 0)),
		_title(Font("", 0))
{
}

Panel::Panel(DefaultPlotConfiguration& defaults) :
		_id(--PANEL_COUNTER),
		_index(defaults._defaultPanel._index),
		_resolution(defaults._defaultPanel._resolution),
		_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),
		_font(defaults._defaultPanel.getFont()),
		_title(defaults._defaultPanel.getFont())
{
}

Panel::Panel(Page* page) :
		_id(--PANEL_COUNTER),
		_index(-1),
		_resolution(DefaultPlotConfiguration::getInstance()._defaultPanel._resolution),
		_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),
		_font(Font(
					DefaultPlotConfiguration::getInstance()._defaultPanel.getFont()._name.empty() ?
							page->getFont()._name : DefaultPlotConfiguration::getInstance()._defaultPanel.getFont()._name,
					DefaultPlotConfiguration::getInstance()._defaultPanel.getFont()._size != 0 ?
							DefaultPlotConfiguration::getInstance()._defaultPanel.getFont()._size : page->getFont()._size)),
		_title(_font)
{
}

Panel::~Panel() {

}

Font Panel::getTitleFont() {
	Font titleFont(_title.getFont());
	if (titleFont._name == "")
		titleFont._name = _font._name;
	if (titleFont._size == 0)
		titleFont._size = _font._size;
	return titleFont;
}

void Panel::reserveSpaceForTitle(double& topSpace, double& bottomSpace, double& titleHeight) {
	LabelRowInfo titleRows(Label::getRowNumber(_title));
	if (titleRows->empty())
		return;

	CharSize lCharSizeTitle;

	Font titleFont(getTitleFont());
	PlPlotUtil::setPlFont(titleFont, &_title._style);
	lCharSizeTitle = PlPlotUtil::getCharacterSizeInPlPage(_page);

	titleHeight = (titleRows->size() + PlPlotUtil::LINE_SPACE_TITLE * (titleRows->size() + 1)) * lCharSizeTitle.second;

	switch (_titlePosition)
	{
		case PlotCommon::Position::POS_TOP :
			topSpace += titleHeight;
			break;
		case PlotCommon::Position::POS_BOTTOM :
			bottomSpace += titleHeight;
			break;
		default :
			//Not possible - Nothing to do
			;
	}
}

void Panel::drawTitle(std::shared_ptr<plstream>& pls) {
	LabelRowInfo titleRows(Label::getRowNumber(_title));
	if (titleRows->empty())
		return;

	if ((_titlePosition != PlotCommon::Position::POS_TOP) && (_titlePosition != PlotCommon::Position::POS_BOTTOM))
		return;

	// Compute panel coordinate in the page
	Bounds lBounds = getBoundsInPlPage();

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

	Font titleFont(getTitleFont());
	PlPlotUtil::setPlFont(titleFont, &_title._style);

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

	float lRowDisp = -0.5 - PlPlotUtil::LINE_SPACE_TITLE;

	// 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 + PlPlotUtil::LINE_SPACE_TITLE);
	}

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


void Panel::draw(std::shared_ptr<plstream>& pls) {
	if (_drawn)
		//panel is already drawn => no draw background and title
		return;

	// Draw background
	fillBackground(pls);

	// write title with dedicated position and align
	drawTitle(pls);

	_drawn = true;
}

/**
 * @brief Write panel context
 */
void Panel::writeContext(std::shared_ptr<plstream>& /*pls*/, ContextFileWriter& writer) {
	Bounds lBounds = getBoundsInPlPage();
	writer.addAttribute("id", std::to_string(_id).c_str());
	if (_page->_orientation == PlotCommon::Orientation::PORTRAIT)
	{
		writer.addAttribute("x", std::to_string(lBounds._y*std::get<0>(_page->getSize())).c_str());
		writer.addAttribute("y", std::to_string(lBounds._x*std::get<1>(_page->getSize())).c_str());
		writer.addAttribute("width", std::to_string(lBounds._height*std::get<0>(_page->getSize())).c_str());
		writer.addAttribute("height", std::to_string(lBounds._width*std::get<1>(_page->getSize())).c_str());
	}
	else
	{
		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());
	}

}

void Panel::fillBackground(std::shared_ptr<plstream>& pls) {
	// 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);
	}

	// Compute panel coordinate in the page
	Bounds lBounds = getBoundsInPlPage();

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

	// Set window size.
	pls->wind(0, 1, 0, 1);

	// Fill background.
	PLFLT px[] = { 0, 0, 1, 1 };
	PLFLT py[] = { 0, 1, 1, 0 };
	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());
	}

	pls->col0(0);
}

void Panel::drawMessage(std::shared_ptr<plstream>& pls, std::string& message) {
	Bounds lBounds = getBoundsInPlPage();

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

	// Set window size.
	pls->wind(0, 1, 0, 1);

	pls->col0(0);

	PlPlotUtil::setPlFont(_font);

	pls->ptex (0.5, 0.5, 0.5, 0, 0.5, message.c_str());

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

void Panel::drawEmptyPanel(std::shared_ptr<plstream>& pls)
{
	Bounds lBounds = getBoundsInPlPage();

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

	// Set window size.
	pls->wind(0, 1, 0, 1);


	pls->col0(0);

	//Draw panel border
	PLFLT xBorder[5] = {0,0,1,1,0};
	PLFLT yBorder[5] = {0,1,1,0,0};

	pls->lsty(static_cast<int>(getPlLineStyle(LineStyle::LONG_SPACED_DOT)));
	pls->width(1);
	pls->line(5,xBorder,yBorder);

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

	//Draw text
	PlPlotUtil::setPlFont(_font);
	std::string emptyText = "Empty panel ";
	if (_index > -1)
	{
		emptyText += "#";
		emptyText += std::to_string(_index);
	}
	else {
		emptyText += "(Id : ";
		emptyText += std::to_string(_id);
		emptyText += ")";
	}
	drawMessage(pls, emptyText);
}

void Panel::drawNoData(std::shared_ptr<plstream>& pls) {
	std::string noDataText = "NO DATA";
	drawMessage(pls, noDataText);
}

Bounds Panel::getBoundsInPlPage() {
	Bounds drawableBounds;
	//Drawable bounds in PlPlot page
	_page->getDrawableBoundsInPlPage(drawableBounds);

	//Panel bounds is relative to the drawable bounds => rewrite it relative to the PlPlot page
	Bounds panelBounds;
	panelBounds._x = drawableBounds._x + drawableBounds._width * _bounds._x;
	panelBounds._y = drawableBounds._y + drawableBounds._height * _bounds._y;
	panelBounds._width = drawableBounds._width * _bounds._width;
	panelBounds._height = drawableBounds._height * _bounds._height;

	return panelBounds;
}

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.getTitle()->_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.getFont();
	for (auto axe : panel._axes) {
		if (axe.second != nullptr)
			axe.second.get()->dump(out);
	}
	return out;
}

} /* namespace plot */