diff --git a/poincare/Makefile b/poincare/Makefile index ddece8982..8d8236035 100644 --- a/poincare/Makefile +++ b/poincare/Makefile @@ -46,6 +46,7 @@ objs += $(addprefix poincare/src/layout/,\ matrix_layout.o\ nth_root_layout.o\ parenthesis_layout.o\ + product_layout.o\ string_layout.o\ sum_layout.o\ subscript_layout.o\ diff --git a/poincare/src/layout/product_layout.cpp b/poincare/src/layout/product_layout.cpp new file mode 100644 index 000000000..b5de1234b --- /dev/null +++ b/poincare/src/layout/product_layout.cpp @@ -0,0 +1,78 @@ +#include "product_layout.h" +#include +#include + +ProductLayout::ProductLayout(ExpressionLayout * lowerBoundLayout, ExpressionLayout * upperBoundLayout, ExpressionLayout * argumentLayout) : + ExpressionLayout(), + m_lowerBoundLayout(lowerBoundLayout), + m_upperBoundLayout(upperBoundLayout), + m_argumentLayout(argumentLayout) +{ + m_lowerBoundLayout->setParent(this); + m_upperBoundLayout->setParent(this); + m_argumentLayout->setParent(this); + m_baseline = max(m_upperBoundLayout->size().height()+k_boundHeightMargin+k_symbolHeight, m_argumentLayout->baseline()); +} + +ProductLayout::~ProductLayout() { + delete m_lowerBoundLayout; + delete m_upperBoundLayout; + delete m_argumentLayout; +} + +void ProductLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) { + KDSize upperBoundSize = m_upperBoundLayout->size(); + KDSize lowerBoundSize = m_lowerBoundLayout->size(); + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-k_symbolHeight), + k_lineThickness, k_symbolHeight), expressionColor); + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2), + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-k_symbolHeight), + k_symbolWidth, k_lineThickness), expressionColor); + ctx->fillRect(KDRect(p.x() + max(max(0, (upperBoundSize.width()-k_symbolWidth)/2), (lowerBoundSize.width()-k_symbolWidth)/2)+k_symbolWidth, + p.y() + max(upperBoundSize.height()+k_boundHeightMargin, m_argumentLayout->baseline()-k_symbolHeight), + k_lineThickness, k_symbolHeight), expressionColor); +} + +KDSize ProductLayout::computeSize() { + KDSize argumentSize = m_argumentLayout->size(); + KDSize lowerBoundSize = m_lowerBoundLayout->size(); + KDSize upperBoundSize = m_upperBoundLayout->size(); + return KDSize( + max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin+argumentSize.width(), + m_baseline + max(k_boundHeightMargin+lowerBoundSize.height(), argumentSize.height() - m_argumentLayout->baseline()) + ); +} + +ExpressionLayout * ProductLayout::child(uint16_t index) { + switch (index) { + case 0: + return m_upperBoundLayout; + case 1: + return m_lowerBoundLayout; + case 2: + return m_argumentLayout; + default: + return nullptr; + } +} + +KDPoint ProductLayout::positionOfChild(ExpressionLayout * child) { + KDSize lowerBoundSize = m_lowerBoundLayout->size(); + KDSize upperBoundSize = m_upperBoundLayout->size(); + KDCoordinate x = 0; + KDCoordinate y = 0; + if (child == m_lowerBoundLayout) { + x = max(max(0, (k_symbolWidth-lowerBoundSize.width())/2), (upperBoundSize.width()-lowerBoundSize.width())/2); + y = m_baseline + k_boundHeightMargin; + } else if (child == m_upperBoundLayout) { + x = max(max(0, (k_symbolWidth-upperBoundSize.width())/2), (lowerBoundSize.width()-upperBoundSize.width())/2); + y = m_baseline - k_symbolHeight- k_boundHeightMargin-upperBoundSize.height(); + } else if (child == m_argumentLayout) { + x = max(max(k_symbolWidth, lowerBoundSize.width()), upperBoundSize.width())+k_argumentWidthMargin; + y = m_baseline - m_argumentLayout->baseline(); + } else { + assert(false); + } + return KDPoint(x,y); +} diff --git a/poincare/src/layout/product_layout.h b/poincare/src/layout/product_layout.h new file mode 100644 index 000000000..5011b2a72 --- /dev/null +++ b/poincare/src/layout/product_layout.h @@ -0,0 +1,27 @@ +#ifndef POINCARE_PRODUCT_LAYOUT_H +#define POINCARE_PRODUCT_LAYOUT_H + +#include +#include + +class ProductLayout : public ExpressionLayout { +public: + ProductLayout(ExpressionLayout * lowerBoundLayout, ExpressionLayout * upperBoundLayout, ExpressionLayout * argumentLayout); + ~ProductLayout(); +protected: + void render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) override; + KDSize computeSize() override; + ExpressionLayout * child(uint16_t index) override; + KDPoint positionOfChild(ExpressionLayout * child) override; +private: + constexpr static KDCoordinate k_symbolHeight = 15; + constexpr static KDCoordinate k_symbolWidth = 9; + constexpr static KDCoordinate k_boundHeightMargin = 2; + constexpr static KDCoordinate k_argumentWidthMargin = 2; + constexpr static KDCoordinate k_lineThickness = 1; + ExpressionLayout * m_lowerBoundLayout; + ExpressionLayout * m_upperBoundLayout; + ExpressionLayout * m_argumentLayout; +}; + +#endif