/* * 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; //Auto id set to a negative number to preserve id defined in request int Panel::PANEL_COUNTER = -1; 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& 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& pls, ContextFileWriter& writer) { Bounds lBounds = getCoordinateInPlPage(pls.get(), _bounds, _page); 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& 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()); } } void Panel::drawEmptyPanel(std::shared_ptr& pls) { 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(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(getPlLineStyle(LineStyle::LONG_SPACED_DOT))); pls->width(1); pls->line(5,xBorder,yBorder); //Draw text pls->schr(getPlFontDef(_font), getPlFontScaleFactor(_font)); std::string emptyText = "Empty panel (Id : "; emptyText += std::to_string(_id); emptyText += ")"; pls->ptex (0.5, 0.5, 0.5, 0, 0.5, emptyText.c_str()); // Set window size. pls->wind(lBounds._x, lBounds._x + lBounds._width, lBounds._y, lBounds._y + lBounds._height); } 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 */