Blame view

Modif/epsilon-master/poincare/src/layout/bracket_pair_layout.cpp 6.27 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  #include "bracket_pair_layout.h"
  #include "horizontal_layout.h"
  #include <poincare/expression_layout_cursor.h>
  #include <poincare/layout_engine.h>
  extern "C" {
  #include <assert.h>
  #include <stdlib.h>
  }
  
  namespace Poincare {
  
  ExpressionLayout * BracketPairLayout::clone() const {
    BracketPairLayout * layout = new BracketPairLayout(const_cast<BracketPairLayout *>(this)->operandLayout(), true);
    return layout;
  }
  
  void BracketPairLayout::collapseSiblingsAndMoveCursor(ExpressionLayoutCursor * cursor) {
    // If the operand layout is not an HorizontalLayout, replace it with one.
    if (!operandLayout()->isHorizontal()) {
      ExpressionLayout * previousOperand = operandLayout();
      HorizontalLayout * horizontalOperandLayout = new HorizontalLayout(previousOperand, false);
      replaceChild(previousOperand, horizontalOperandLayout, false);
    }
    ExpressionLayout::collapseOnDirection(HorizontalDirection::Right, 0);
    cursor->setPointedExpressionLayout(operandLayout());
    cursor->setPosition(ExpressionLayoutCursor::Position::Left);
  }
  
  void BracketPairLayout::deleteBeforeCursor(ExpressionLayoutCursor * cursor) {
    if (cursor->isEquivalentTo(ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left))) {
      // Case: Left of the operand. Delete the layout, keep the operand.
      replaceWithAndMoveCursor(operandLayout(), true, cursor);
      return;
    }
    ExpressionLayout::deleteBeforeCursor(cursor);
  }
  
  ExpressionLayoutCursor BracketPairLayout::cursorLeftOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) {
    // Case: Left of the operand. Go Left of the brackets.
    if (operandLayout()
      && cursor.pointedExpressionLayout() == operandLayout()
      && cursor.position() == ExpressionLayoutCursor::Position::Left)
    {
      return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Left);
    }
    assert(cursor.pointedExpressionLayout() == this);
    // Case: Right of the brackets. Go Right of the operand.
    if (cursor.position() == ExpressionLayoutCursor::Position::Right) {
      assert(operandLayout() != nullptr);
      return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Right);
    }
    assert(cursor.position() == ExpressionLayoutCursor::Position::Left);
    // Case: Left of the brackets. Ask the parent.
    if (m_parent) {
      return m_parent->cursorLeftOf(cursor, shouldRecomputeLayout);
    }
    return ExpressionLayoutCursor();
  }
  
  ExpressionLayoutCursor BracketPairLayout::cursorRightOf(ExpressionLayoutCursor cursor, bool * shouldRecomputeLayout) {
    // Case: Right of the operand. Go Right of the brackets.
    if (operandLayout()
      && cursor.pointedExpressionLayout() == operandLayout()
      && cursor.position() == ExpressionLayoutCursor::Position::Right)
    {
      return ExpressionLayoutCursor(this, ExpressionLayoutCursor::Position::Right);
    }
    assert(cursor.pointedExpressionLayout() == this);
    // Case: Left of the brackets. Go Left of the operand.
    if (cursor.position() == ExpressionLayoutCursor::Position::Left) {
      assert(operandLayout() != nullptr);
      return ExpressionLayoutCursor(operandLayout(), ExpressionLayoutCursor::Position::Left);
    }
    assert(cursor.position() == ExpressionLayoutCursor::Position::Right);
    // Case: Right of the brackets. Ask the parent.
    cursor.setPointedExpressionLayout(this);
    if (m_parent) {
      return m_parent->cursorRightOf(cursor, shouldRecomputeLayout);
    }
    return ExpressionLayoutCursor();
  }
  
  int BracketPairLayout::writeTextInBuffer(char * buffer, int bufferSize) const {
    if (bufferSize == 0) {
      return -1;
    }
    buffer[bufferSize-1] = 0;
  
    // Write the opening bracket
    int numberOfChar = 0;
    buffer[numberOfChar++] = '[';
    if (numberOfChar >= bufferSize-1) { return bufferSize-1;}
  
    // Write the argument
    numberOfChar += const_cast<Poincare::BracketPairLayout *>(this)->operandLayout()->writeTextInBuffer(buffer+numberOfChar, bufferSize-numberOfChar);
    if (numberOfChar >= bufferSize-1) { return bufferSize-1; }
  
    // Write the closing bracket
    buffer[numberOfChar++] = ']';
    buffer[numberOfChar] = 0;
    return numberOfChar;
  }
  
  void BracketPairLayout::render(KDContext * ctx, KDPoint p, KDColor expressionColor, KDColor backgroundColor) {
    const KDCoordinate k_widthMargin = widthMargin();
    const KDCoordinate k_externWidthMargin = externWidthMargin();
    KDSize operandSize = operandLayout()->size();
    KDCoordinate verticalBarHeight = operandLayout()->size().height() + 2*k_verticalMargin;
    ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor);
    ctx->fillRect(KDRect(p.x()+k_externWidthMargin+operandSize.width()+2*k_widthMargin+k_lineThickness, p.y()+verticalExternMargin(), k_lineThickness, verticalBarHeight), expressionColor);
    if (renderTopBar()) {
      ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor);
      ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y() + verticalExternMargin(), k_bracketWidth, k_lineThickness), expressionColor);
    }
    if (renderBottomBar()) {
      ctx->fillRect(KDRect(p.x()+k_externWidthMargin, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor);
      ctx->fillRect(KDRect(p.x()+k_externWidthMargin+2*k_lineThickness+operandSize.width()+2*k_widthMargin-k_bracketWidth, p.y()+verticalExternMargin()+verticalBarHeight-k_lineThickness, k_bracketWidth, k_lineThickness), expressionColor);
    }
  }
  
  KDSize BracketPairLayout::computeSize() {
    const KDCoordinate k_widthMargin = widthMargin();
    const KDCoordinate k_externWidthMargin = externWidthMargin();
    KDSize operandSize = operandLayout()->size();
    return KDSize(operandSize.width() + 2*k_externWidthMargin + 2*k_widthMargin + 2*k_lineThickness, operandSize.height() + 2 * k_verticalMargin + 2*verticalExternMargin());
  }
  
  void BracketPairLayout::computeBaseline() {
    m_baseline = operandLayout()->baseline() + k_verticalMargin + verticalExternMargin();
    m_baselined = true;
  }
  
  KDPoint BracketPairLayout::positionOfChild(ExpressionLayout * child) {
    const KDCoordinate k_widthMargin = widthMargin();
    const KDCoordinate k_externWidthMargin = externWidthMargin();
    return KDPoint(k_widthMargin+k_externWidthMargin+k_lineThickness, k_verticalMargin + verticalExternMargin());
  }
  
  }