/* * LayoutVertical.hh * * Created on: Sep, 2, 2014 * Author: AKKA */ #include "LayoutVertical.hh" #include "PlotLogger.hh" #include "DecoratorPlot.hh" #include 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; } void LayoutVertical::computePanelsPosition (std::vector> _plots) { // Add panels constraint to the layout for (auto plot : boost::adaptors::reverse(_plots)) { DecoratorPlot *decoratorPlot = dynamic_cast< DecoratorPlot* >(plot.get()); if (decoratorPlot != NULL) if (!decoratorPlot->_isStandalone) continue; this->addPanel ( plot->getLayoutConstraint(), plot->_panel->_preferedWidth, plot->_panel->_preferedHeight); } // Reset layout this->reset(); for (auto plot : boost::adaptors::reverse(_plots)) { DecoratorPlot *decoratorPlot = dynamic_cast< DecoratorPlot* >(plot.get()); if (decoratorPlot != NULL) if (!decoratorPlot->_isStandalone) continue; plot->_panel->_bounds = this->getNextBounds (plot->getLayoutConstraint()); } } }