mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/calculation] Fix calculation height computation
It was done in two places before, which created inconsistencies
This commit is contained in:
committed by
EmilieNumworks
parent
0379327b06
commit
a56a73b0ba
@@ -78,7 +78,13 @@ KDCoordinate IllustratedListController::rowHeight(int j) {
|
||||
return 0;
|
||||
}
|
||||
Shared::ExpiringPointer<Calculation> calculation = m_calculationStore.calculationAtIndex(calculationIndex);
|
||||
return calculation->height(App::app()->localContext(), Metric::CommonSmallMargin, ScrollableThreeExpressionsView::k_margin, true, true) + Metric::CellSeparatorThickness;
|
||||
constexpr bool expanded = true;
|
||||
KDCoordinate result = calculation->memoizedHeight(expanded);
|
||||
if (result < 0) {
|
||||
result = ScrollableThreeExpressionsCell::Height(calculation.pointer());
|
||||
calculation->setMemoizedHeight(expanded, result);
|
||||
}
|
||||
return result + Metric::CellSeparatorThickness;
|
||||
}
|
||||
|
||||
int IllustratedListController::typeAtLocation(int i, int j) {
|
||||
|
||||
@@ -65,6 +65,17 @@ void ScrollableThreeExpressionsView::setCalculation(Calculation * calculation) {
|
||||
layoutSubviews();
|
||||
}
|
||||
|
||||
KDCoordinate ScrollableThreeExpressionsCell::Height(Calculation * calculation) {
|
||||
ScrollableThreeExpressionsCell cell;
|
||||
cell.setCalculation(calculation);
|
||||
KDRect leftFrame = KDRectZero;
|
||||
KDRect centerFrame = KDRectZero;
|
||||
KDRect approximateSignFrame = KDRectZero;
|
||||
KDRect rightFrame = KDRectZero;
|
||||
cell.subviewFrames(&leftFrame, ¢erFrame, &approximateSignFrame, &rightFrame);
|
||||
return leftFrame.unionedWith(centerFrame).unionedWith(rightFrame).height();
|
||||
}
|
||||
|
||||
void ScrollableThreeExpressionsCell::didBecomeFirstResponder() {
|
||||
reinitSelection();
|
||||
Container::activeApp()->setFirstResponder(&m_view);
|
||||
|
||||
@@ -17,6 +17,9 @@ public:
|
||||
}
|
||||
void resetMemoization();
|
||||
void setCalculation(Calculation * calculation);
|
||||
void subviewFrames(KDRect * leftFrame, KDRect * centerFrame, KDRect * approximateSignFrame, KDRect * rightFrame) {
|
||||
return m_contentCell.subviewFrames(leftFrame, centerFrame, approximateSignFrame, rightFrame);
|
||||
}
|
||||
private:
|
||||
class ContentCell : public Shared::AbstractScrollableMultipleExpressionsView::ContentCell {
|
||||
public:
|
||||
@@ -29,12 +32,13 @@ private:
|
||||
};
|
||||
|
||||
ContentCell * contentCell() override { return &m_contentCell; };
|
||||
const ContentCell * constContentCell() const override { return &m_contentCell; };
|
||||
const ContentCell * constContentCell() const override { return &m_contentCell; };
|
||||
ContentCell m_contentCell;
|
||||
};
|
||||
|
||||
class ScrollableThreeExpressionsCell : public TableCell, public Responder {
|
||||
public:
|
||||
static KDCoordinate Height(Calculation * calculation);
|
||||
ScrollableThreeExpressionsCell() :
|
||||
Responder(nullptr),
|
||||
m_view(this) {}
|
||||
@@ -59,6 +63,9 @@ public:
|
||||
void setSelectedSubviewPosition(ScrollableThreeExpressionsView::SubviewPosition subviewPosition) { m_view.setSelectedSubviewPosition(subviewPosition); }
|
||||
|
||||
void reinitSelection();
|
||||
void subviewFrames(KDRect * leftFrame, KDRect * centerFrame, KDRect * approximateSignFrame, KDRect * rightFrame) {
|
||||
return m_view.subviewFrames(leftFrame, centerFrame, approximateSignFrame, rightFrame);
|
||||
}
|
||||
private:
|
||||
// Remove label margin added by TableCell because they're already handled by ScrollableThreeExpressionsView
|
||||
KDCoordinate labelMargin() const override { return 0; }
|
||||
|
||||
@@ -125,125 +125,12 @@ Layout Calculation::createApproximateOutputLayout(Context * context, bool * coul
|
||||
}
|
||||
}
|
||||
|
||||
KDCoordinate Calculation::height(Context * context, KDCoordinate topBottomMargin, KDCoordinate verticalMarginAroundLayouts, bool expanded, bool forceSingleLine, LayoutsCanBeSingleLineFunction canBeSingleLine) {
|
||||
/* WARNING: this method must return the same result as
|
||||
* Calculation::HistoryViewCell::layoutSubviews. */
|
||||
|
||||
KDCoordinate result = expanded ? m_expandedHeight : m_height;
|
||||
if (result >= 0) {
|
||||
// Height already computed
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get input information
|
||||
Layout inputLayout = createInputLayout();
|
||||
KDCoordinate inputHeight = inputLayout.layoutSize().height();
|
||||
KDCoordinate inputWidth = inputLayout.layoutSize().width();
|
||||
KDCoordinate inputBaseline = inputLayout.baseline();
|
||||
|
||||
// Get output information
|
||||
KDCoordinate outputWidth;
|
||||
KDCoordinate outputBaseline;
|
||||
KDCoordinate outputHeightBelowBaseline;
|
||||
|
||||
DisplayOutput displayType = displayOutput(context);
|
||||
/* If the display output is ExactAndApproximateToggle, we want to use the
|
||||
* expanded width to compute if the calculaton is in single line or not. */
|
||||
bool shouldComputeMaxOutputWidthForSingleLine = !forceSingleLine && (!expanded && displayType == DisplayOutput::ExactAndApproximateToggle);
|
||||
|
||||
{
|
||||
bool displaysExactOnly = displayType == DisplayOutput::ExactOnly;
|
||||
bool displayApproximateOnly = displayType == DisplayOutput::ApproximateOnly
|
||||
|| (!expanded
|
||||
&& (displayType == DisplayOutput::ExactAndApproximateToggle));
|
||||
|
||||
KDCoordinate exactOutputWidth = 0;
|
||||
KDCoordinate exactOutputBaseline = 0;
|
||||
KDCoordinate exactOutputBelowBaseline = 0;
|
||||
|
||||
// Get exact output info if needed
|
||||
bool displaysExact = displaysExactOnly || !displayApproximateOnly;
|
||||
if (displaysExact || shouldComputeMaxOutputWidthForSingleLine) {
|
||||
bool couldNotCreateExactLayout = false;
|
||||
Poincare::Layout exactLayout = createExactOutputLayout(&couldNotCreateExactLayout);
|
||||
if (couldNotCreateExactLayout) {
|
||||
if (!displaysExactOnly) {
|
||||
displayType = DisplayOutput::ApproximateOnly;
|
||||
forceDisplayOutput(displayType);
|
||||
displaysExactOnly = false;
|
||||
displayApproximateOnly = true;
|
||||
shouldComputeMaxOutputWidthForSingleLine = false;
|
||||
outputWidth = 0;
|
||||
} else {
|
||||
/* We should only display the exact result, but we cannot create it
|
||||
* -> raise an exception. */
|
||||
ExceptionCheckpoint::Raise();
|
||||
}
|
||||
} else {
|
||||
KDSize exactSize = exactLayout.layoutSize();
|
||||
outputWidth = exactSize.width();
|
||||
if (displaysExact) {
|
||||
exactOutputWidth = exactSize.width();
|
||||
exactOutputBaseline = exactLayout.baseline();
|
||||
exactOutputBelowBaseline = exactSize.height() - exactOutputBaseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KDCoordinate approximateOutputWidth = 0;
|
||||
KDCoordinate approximateOutputBaseline = 0;
|
||||
KDCoordinate approximateOutputBelowBaseline = 0;
|
||||
|
||||
// Get approximate output info if needed
|
||||
bool displaysApproximate = displayApproximateOnly || !displaysExactOnly;
|
||||
if (displaysApproximate || shouldComputeMaxOutputWidthForSingleLine) {
|
||||
bool couldNotCreateApproximateLayout = false;
|
||||
Layout approximateLayout = createApproximateOutputLayout(context, &couldNotCreateApproximateLayout);
|
||||
if (couldNotCreateApproximateLayout) {
|
||||
Poincare::ExceptionCheckpoint::Raise();
|
||||
}
|
||||
KDSize approximateOutputSize = approximateLayout.layoutSize();
|
||||
outputWidth += approximateOutputSize.width();
|
||||
if (displaysApproximate) {
|
||||
approximateOutputWidth = approximateOutputSize.width();
|
||||
approximateOutputBaseline = approximateLayout.baseline();
|
||||
approximateOutputBelowBaseline = approximateOutputSize.height() - approximateOutputBaseline;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the output info
|
||||
if (shouldComputeMaxOutputWidthForSingleLine || (exactOutputWidth > 0 && approximateOutputWidth > 0)) {
|
||||
outputWidth += AbstractScrollableMultipleExpressionsView::StandardApproximateViewAndMarginsSize();
|
||||
}
|
||||
outputBaseline = std::max(exactOutputBaseline, approximateOutputBaseline);
|
||||
outputHeightBelowBaseline = std::max(exactOutputBelowBaseline, approximateOutputBelowBaseline);
|
||||
}
|
||||
|
||||
if (forceSingleLine || canBeSingleLine(inputWidth, outputWidth)) {
|
||||
result = std::max(inputBaseline, outputBaseline) // Above the baseline
|
||||
+ std::max(static_cast<KDCoordinate>(inputHeight - inputBaseline), outputHeightBelowBaseline) // Below the baseline
|
||||
+ 2 * verticalMarginAroundLayouts;
|
||||
void Calculation::setMemoizedHeight(bool expanded, KDCoordinate height) {
|
||||
if (expanded) {
|
||||
m_expandedHeight = height;
|
||||
} else {
|
||||
result = inputHeight + outputBaseline + outputHeightBelowBaseline + 4 * verticalMarginAroundLayouts;
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
// Add the top and bottom margins
|
||||
result += 2 * topBottomMargin;
|
||||
|
||||
/* For all display outputs except ExactAndApproximateToggle, the selected
|
||||
* height and the usual height are identical. We update both heights in
|
||||
* theses cases. */
|
||||
if (displayOutput(context) != DisplayOutput::ExactAndApproximateToggle) {
|
||||
m_height = result;
|
||||
m_expandedHeight = result;
|
||||
} else {
|
||||
if (expanded) {
|
||||
m_expandedHeight = result;
|
||||
} else {
|
||||
m_height = result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Calculation::DisplayOutput Calculation::displayOutput(Context * context) {
|
||||
|
||||
@@ -84,8 +84,8 @@ public:
|
||||
Poincare::Layout createApproximateOutputLayout(Poincare::Context * context, bool * couldNotCreateApproximateLayout);
|
||||
|
||||
// Memoization of height
|
||||
typedef bool (*LayoutsCanBeSingleLineFunction)(KDCoordinate inputWidth, KDCoordinate outputWidth);
|
||||
KDCoordinate height(Poincare::Context * context, KDCoordinate topBottomMargin, KDCoordinate verticalMarginAroundLayouts, bool expanded, bool forceSingleLine, LayoutsCanBeSingleLineFunction canbeSingleLine = [](KDCoordinate inputLayoutWidth, KDCoordinate outputLayoutWidth) { assert(false); return true; });
|
||||
KDCoordinate memoizedHeight(bool expanded) { return expanded ? m_expandedHeight : m_height; }
|
||||
void setMemoizedHeight(bool expanded, KDCoordinate height);
|
||||
|
||||
// Displayed output
|
||||
DisplayOutput displayOutput(Poincare::Context * context);
|
||||
|
||||
@@ -206,13 +206,13 @@ KDCoordinate HistoryController::rowHeight(int j) {
|
||||
return 0;
|
||||
}
|
||||
Shared::ExpiringPointer<Calculation> calculation = calculationAtIndex(j);
|
||||
return calculation->height(
|
||||
App::app()->localContext(),
|
||||
HistoryViewCell::k_margin,
|
||||
HistoryViewCell::k_inputOutputViewsVerticalMargin,
|
||||
j == selectedRow() && selectedSubviewType() == SubviewType::Output,
|
||||
false,
|
||||
&HistoryViewCell::LayoutsCanBeSingleLine);
|
||||
bool expanded = j == selectedRow() && selectedSubviewType() == SubviewType::Output;
|
||||
KDCoordinate result = calculation->memoizedHeight(expanded);
|
||||
if (result < 0) {
|
||||
result = HistoryViewCell::Height(calculation.pointer(), expanded);
|
||||
calculation->setMemoizedHeight(expanded, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int HistoryController::typeAtLocation(int i, int j) {
|
||||
|
||||
@@ -34,12 +34,22 @@ void HistoryViewCellDataSource::setSelectedSubviewType(SubviewType subviewType,
|
||||
|
||||
/* HistoryViewCell */
|
||||
|
||||
KDCoordinate HistoryViewCell::Height(Calculation * calculation, bool expanded) {
|
||||
HistoryViewCell cell(nullptr);
|
||||
cell.setCalculation(calculation, expanded);
|
||||
KDRect ellipsisFrame = KDRectZero;
|
||||
KDRect inputFrame = KDRectZero;
|
||||
KDRect outputFrame = KDRectZero;
|
||||
cell.computeSubviewFrames(Ion::Display::Width, KDCOORDINATE_MAX, &ellipsisFrame, &inputFrame, &outputFrame);
|
||||
return k_margin + inputFrame.unionedWith(outputFrame).height() + k_margin;
|
||||
}
|
||||
|
||||
HistoryViewCell::HistoryViewCell(Responder * parentResponder) :
|
||||
Responder(parentResponder),
|
||||
m_calculationCRC32(0),
|
||||
m_calculationDisplayOutput(Calculation::DisplayOutput::Unknown),
|
||||
m_calculationAdditionInformation(Calculation::AdditionalInformationType::None),
|
||||
m_inputView(this, k_inputOutputViewsHorizontalMargin, k_inputOutputViewsVerticalMargin),
|
||||
m_inputView(this, k_inputViewHorizontalMargin, k_inputOutputViewsVerticalMargin),
|
||||
m_scrollableOutputView(this),
|
||||
m_calculationExpanded(false),
|
||||
m_calculationSingleLine(false)
|
||||
@@ -154,23 +164,37 @@ View * HistoryViewCell::subviewAtIndex(int index) {
|
||||
return views[index];
|
||||
}
|
||||
|
||||
bool HistoryViewCell::LayoutsCanBeSingleLine(KDCoordinate inputLayoutWidth, KDCoordinate outputLayoutWidth) {
|
||||
return ViewsCanBeSingleLine(inputLayoutWidth + 2 * k_inputOutputViewsHorizontalMargin, outputLayoutWidth + 2 * k_inputOutputViewsHorizontalMargin);
|
||||
}
|
||||
|
||||
bool HistoryViewCell::ViewsCanBeSingleLine(KDCoordinate inputViewWidth, KDCoordinate outputViewWidth) {
|
||||
// k_margin is the separation between the input and output.
|
||||
return (inputViewWidth + k_margin + outputViewWidth) < Ion::Display::Width - Metric::EllipsisCellWidth;
|
||||
}
|
||||
|
||||
void HistoryViewCell::layoutSubviews(bool force) {
|
||||
KDCoordinate maxFrameWidth = bounds().width();
|
||||
if (displayedEllipsis()) {
|
||||
m_ellipsis.setFrame(KDRect(maxFrameWidth - Metric::EllipsisCellWidth, 0, Metric::EllipsisCellWidth, bounds().height()), force);
|
||||
maxFrameWidth -= Metric::EllipsisCellWidth;
|
||||
} else {
|
||||
m_ellipsis.setFrame(KDRectZero, force); // Required to mark previous rect as dirty
|
||||
KDRect frameBounds = bounds();
|
||||
if (bounds().width() <= 0 || bounds().height() <= 0) {
|
||||
// TODO Make this behaviour in a non-virtual layoutSublviews, and all layout subviews should become privateLayoutSubviews
|
||||
return;
|
||||
}
|
||||
KDRect ellipsisFrame = KDRectZero;
|
||||
KDRect inputFrame = KDRectZero;
|
||||
KDRect outputFrame = KDRectZero;
|
||||
computeSubviewFrames(frameBounds.width(), frameBounds.height(), &ellipsisFrame, &inputFrame, &outputFrame);
|
||||
|
||||
m_ellipsis.setFrame(ellipsisFrame, force); // Required even if ellipsisFrame is KDRectZero, to mark previous rect as dirty
|
||||
m_inputView.setFrame(inputFrame,force);
|
||||
m_scrollableOutputView.setFrame(outputFrame, force);
|
||||
}
|
||||
|
||||
void HistoryViewCell::computeSubviewFrames(KDCoordinate frameWidth, KDCoordinate frameHeight, KDRect * ellipsisFrame, KDRect * inputFrame, KDRect * outputFrame) {
|
||||
assert(ellipsisFrame != nullptr && inputFrame != nullptr && outputFrame != nullptr);
|
||||
|
||||
if (displayedEllipsis()) {
|
||||
*ellipsisFrame = KDRect(frameWidth - Metric::EllipsisCellWidth, 0, Metric::EllipsisCellWidth, frameHeight);
|
||||
frameWidth -= Metric::EllipsisCellWidth;
|
||||
} else {
|
||||
*ellipsisFrame = KDRectZero;
|
||||
}
|
||||
|
||||
KDSize inputSize = m_inputView.minimalSizeForOptimalDisplay();
|
||||
KDSize outputSize = m_scrollableOutputView.minimalSizeForOptimalDisplay();
|
||||
|
||||
@@ -193,18 +217,16 @@ void HistoryViewCell::layoutSubviews(bool force) {
|
||||
outputY += inputSize.height();
|
||||
}
|
||||
|
||||
m_inputView.setFrame(KDRect(
|
||||
*inputFrame = KDRect(
|
||||
0,
|
||||
inputY,
|
||||
std::min(maxFrameWidth, inputSize.width()),
|
||||
inputSize.height()),
|
||||
force);
|
||||
m_scrollableOutputView.setFrame(KDRect(
|
||||
std::max(0, maxFrameWidth - outputSize.width()),
|
||||
std::min(frameWidth, inputSize.width()),
|
||||
inputSize.height());
|
||||
*outputFrame = KDRect(
|
||||
std::max(0, frameWidth - outputSize.width()),
|
||||
outputY,
|
||||
std::min(maxFrameWidth, outputSize.width()),
|
||||
outputSize.height()),
|
||||
force);
|
||||
std::min(frameWidth, outputSize.width()),
|
||||
outputSize.height());
|
||||
}
|
||||
|
||||
void HistoryViewCell::resetMemoization() {
|
||||
|
||||
@@ -33,9 +33,9 @@ class HistoryViewCell : public ::EvenOddCell, public Responder {
|
||||
public:
|
||||
constexpr static KDCoordinate k_margin = Metric::CommonSmallMargin;
|
||||
constexpr static KDCoordinate k_inputOutputViewsVerticalMargin = k_margin;
|
||||
constexpr static KDCoordinate k_inputOutputViewsHorizontalMargin = Shared::AbstractScrollableMultipleExpressionsView::k_horizontalMargin;
|
||||
constexpr static KDCoordinate k_inputViewHorizontalMargin = Shared::AbstractScrollableMultipleExpressionsView::k_horizontalMargin;
|
||||
static KDCoordinate Height(Calculation * calculation, bool expanded);
|
||||
HistoryViewCell(Responder * parentResponder = nullptr);
|
||||
static bool LayoutsCanBeSingleLine(KDCoordinate inputLayoutWidth, KDCoordinate outputLayoutWidth);
|
||||
static bool ViewsCanBeSingleLine(KDCoordinate inputViewWidth, KDCoordinate outputViewWidth);
|
||||
void cellDidSelectSubview(HistoryViewCellDataSource::SubviewType type, HistoryViewCellDataSource::SubviewType previousType = HistoryViewCellDataSource::SubviewType::None);
|
||||
void setEven(bool even) override;
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
Calculation::AdditionalInformationType additionalInformationType() const { return m_calculationAdditionInformation; }
|
||||
private:
|
||||
constexpr static KDCoordinate k_resultWidth = 80;
|
||||
void computeSubviewFrames(KDCoordinate frameWidth, KDCoordinate frameHeight, KDRect * ellipsisFrame, KDRect * inputFrame, KDRect * outputFrame);
|
||||
void reloadScroll();
|
||||
void reloadOutputSelection(HistoryViewCellDataSource::SubviewType previousType);
|
||||
bool displayedEllipsis() const {
|
||||
|
||||
@@ -121,6 +121,41 @@ KDCoordinate AbstractScrollableMultipleExpressionsView::ContentCell::baseline(KD
|
||||
return std::max(std::max(leftViewBaseline, centerViewBaseline), rightViewBaseline);
|
||||
}
|
||||
|
||||
void AbstractScrollableMultipleExpressionsView::ContentCell::subviewFrames(KDRect * leftFrame, KDRect * centerFrame, KDRect * approximateSignFrame, KDRect * rightFrame) {
|
||||
// Subviews sizes
|
||||
KDSize leftSize = leftExpressionView() ? leftExpressionView()->minimalSizeForOptimalDisplay() : KDSizeZero;
|
||||
KDSize centerSize = displayCenter() ? m_centeredExpressionView.minimalSizeForOptimalDisplay() : KDSizeZero;
|
||||
KDSize rightSize = m_rightExpressionView.minimalSizeForOptimalDisplay();
|
||||
|
||||
// Compute baselines
|
||||
KDCoordinate leftBaseline = 0;
|
||||
KDCoordinate centerBaseline = 0;
|
||||
KDCoordinate rightBaseline = 0;
|
||||
KDCoordinate viewBaseline = baseline(&leftBaseline, ¢erBaseline, &rightBaseline);
|
||||
|
||||
// Layout left view
|
||||
KDCoordinate currentWidth = 0;
|
||||
if (leftExpressionView()) {
|
||||
assert(leftFrame != nullptr);
|
||||
*leftFrame = KDRect(currentWidth, viewBaseline - leftBaseline, leftSize);
|
||||
currentWidth += leftSize.width() + AbstractScrollableMultipleExpressionsView::k_horizontalMargin;
|
||||
}
|
||||
|
||||
// Layout center expression
|
||||
if (displayCenter()) {
|
||||
assert(centerFrame != nullptr && approximateSignFrame != nullptr);
|
||||
KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay();
|
||||
*centerFrame = KDRect(currentWidth, viewBaseline - centerBaseline, centerSize);
|
||||
currentWidth += AbstractScrollableMultipleExpressionsView::k_horizontalMargin + centerSize.width();
|
||||
*approximateSignFrame = KDRect(currentWidth, viewBaseline - approximateSignSize.height()/2, approximateSignSize);
|
||||
currentWidth += AbstractScrollableMultipleExpressionsView::k_horizontalMargin + approximateSignSize.width();
|
||||
}
|
||||
|
||||
// Layout right expression
|
||||
assert(rightFrame != nullptr);
|
||||
*rightFrame = KDRect(currentWidth, viewBaseline - rightBaseline, rightSize);
|
||||
}
|
||||
|
||||
KDSize AbstractScrollableMultipleExpressionsView::ContentCell::privateMinimalSizeForOptimalDisplay(bool forceFullDisplay) const {
|
||||
KDCoordinate width = 0;
|
||||
|
||||
@@ -169,35 +204,25 @@ KDCoordinate AbstractScrollableMultipleExpressionsView::ContentCell::StandardApp
|
||||
}
|
||||
|
||||
void AbstractScrollableMultipleExpressionsView::ContentCell::layoutSubviews(bool force) {
|
||||
// Subviews sizes
|
||||
KDSize leftSize = leftExpressionView() ? leftExpressionView()->minimalSizeForOptimalDisplay() : KDSizeZero;
|
||||
KDSize centerSize = displayCenter() ? m_centeredExpressionView.minimalSizeForOptimalDisplay() : KDSizeZero;
|
||||
KDSize rightSize = m_rightExpressionView.minimalSizeForOptimalDisplay();
|
||||
|
||||
// Compute baselines
|
||||
KDCoordinate leftBaseline = 0;
|
||||
KDCoordinate centerBaseline = 0;
|
||||
KDCoordinate rightBaseline = 0;
|
||||
KDCoordinate viewBaseline = baseline(&leftBaseline, ¢erBaseline, &rightBaseline);
|
||||
|
||||
// Layout left view
|
||||
KDCoordinate currentWidth = 0;
|
||||
if (leftExpressionView()) {
|
||||
leftExpressionView()->setFrame(KDRect(currentWidth, viewBaseline - leftBaseline, leftSize), force);
|
||||
currentWidth += leftSize.width() + AbstractScrollableMultipleExpressionsView::k_horizontalMargin;
|
||||
if (bounds().width() <= 0 || bounds().height() <= 0) {
|
||||
// TODO Make this behaviour in a non-virtual layoutSublviews, and all layout subviews should become privateLayoutSubviews
|
||||
return;
|
||||
}
|
||||
|
||||
// Layout center expression
|
||||
if (displayCenter()) {
|
||||
KDSize approximateSignSize = m_approximateSign.minimalSizeForOptimalDisplay();
|
||||
m_centeredExpressionView.setFrame(KDRect(currentWidth, viewBaseline - centerBaseline, centerSize), force);
|
||||
currentWidth += AbstractScrollableMultipleExpressionsView::k_horizontalMargin + centerSize.width();
|
||||
m_approximateSign.setFrame(KDRect(currentWidth, viewBaseline - approximateSignSize.height()/2, approximateSignSize), force);
|
||||
currentWidth += AbstractScrollableMultipleExpressionsView::k_horizontalMargin + approximateSignSize.width();
|
||||
KDRect leftFrame = KDRectZero;
|
||||
KDRect centerFrame = KDRectZero;
|
||||
KDRect approximateSignFrame = KDRectZero;
|
||||
KDRect rightFrame = KDRectZero;
|
||||
subviewFrames(&leftFrame, ¢erFrame, &approximateSignFrame, &rightFrame);
|
||||
if (leftExpressionView() != nullptr) {
|
||||
leftExpressionView()->setFrame(leftFrame, force);
|
||||
}
|
||||
if (centeredExpressionView() != nullptr) {
|
||||
centeredExpressionView()->setFrame(centerFrame, force);
|
||||
}
|
||||
m_approximateSign.setFrame(approximateSignFrame, force);
|
||||
if (rightExpressionView() != nullptr) {
|
||||
rightExpressionView()->setFrame(rightFrame, force);
|
||||
}
|
||||
|
||||
// Layout right expression
|
||||
m_rightExpressionView.setFrame(KDRect(currentWidth, viewBaseline - rightBaseline, rightSize), force);
|
||||
}
|
||||
|
||||
AbstractScrollableMultipleExpressionsView::AbstractScrollableMultipleExpressionsView(Responder * parentResponder, View * contentCell) :
|
||||
|
||||
@@ -68,6 +68,7 @@ protected:
|
||||
int numberOfSubviews() const override;
|
||||
virtual Poincare::Layout layout() const override;
|
||||
KDCoordinate baseline(KDCoordinate * leftBaseline = nullptr, KDCoordinate * centerBaseline = nullptr, KDCoordinate * rightBaseline = nullptr) const;
|
||||
void subviewFrames(KDRect * leftFrame, KDRect * centerFrame, KDRect * approximateSignFrame, KDRect * rightFrame);
|
||||
private:
|
||||
constexpr static const KDFont * k_font = KDFont::LargeFont;
|
||||
const static I18n::Message k_defaultApproximateMessage = I18n::Message::AlmostEqual;
|
||||
|
||||
@@ -117,6 +117,9 @@ KDRect ScrollView::visibleContentRect() {
|
||||
}
|
||||
|
||||
void ScrollView::layoutSubviews(bool force) {
|
||||
if (bounds().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
KDRect r1 = KDRectZero;
|
||||
KDRect r2 = KDRectZero;
|
||||
KDRect innerFrame = decorator()->layoutIndicators(minimalSizeForOptimalDisplay(), contentOffset(), bounds(), &r1, &r2, force);
|
||||
|
||||
@@ -174,5 +174,5 @@ KDRect KDRect::movedTo(KDPoint p) const {
|
||||
}
|
||||
|
||||
bool KDRect::isEmpty() const {
|
||||
return (width() == 0 || height() == 0);
|
||||
return (width() == 0 || height() == 0); //TODO <= 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user