Numworks Epsilon  1.4.1
Graphing Calculator Operating System
list_controller.cpp
Go to the documentation of this file.
1 #include "list_controller.h"
2 #include "../app.h"
3 #include <assert.h>
4 
5 using namespace Shared;
6 using namespace Poincare;
7 
8 namespace Sequence {
9 
10 ListController::ListController(Responder * parentResponder, SequenceStore * sequenceStore, ButtonRowController * header, ButtonRowController * footer) :
11  Shared::ListController(parentResponder, sequenceStore, header, footer, I18n::Message::AddSequence),
12  m_sequenceStore(sequenceStore),
13  m_sequenceTitleCells{},
14  m_expressionCells{},
15  m_parameterController(this, sequenceStore),
16  m_typeParameterController(this, sequenceStore, this, TableCell::Layout::Vertical),
17  m_typeStackController(nullptr, &m_typeParameterController, KDColorWhite, Palette::PurpleDark, Palette::PurpleDark),
18  m_sequenceToolbox()
19 {
20 }
21 
22 const char * ListController::title() {
23  return I18n::translate(I18n::Message::SequenceTab);
24 }
25 
27  int recurrenceDepth = -1;
28  int sequenceDefinition = sequenceDefinitionForRow(selectedRow());
29  Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow()));
30  if (sequenceDefinition == 0) {
31  recurrenceDepth = sequence->numberOfElements()-1;
32  }
33  m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth);
34  return &m_sequenceToolbox;
35 }
36 
37 TextFieldDelegateApp * ListController::textFieldDelegateApp() {
38  return (App *)app();
39 }
40 
42  int numberOfRows = 0;
43  for (int i = 0; i < m_sequenceStore->numberOfFunctions(); i++) {
44  Sequence * sequence = m_sequenceStore->functionAtIndex(i);
45  numberOfRows += sequence->numberOfElements();
46  }
47  if (m_sequenceStore->numberOfFunctions() == m_sequenceStore->maxNumberOfFunctions()) {
48  return numberOfRows;
49  }
50  return 1 + numberOfRows;
51 };
52 
54  if (m_sequenceStore->numberOfFunctions() < m_sequenceStore->maxNumberOfFunctions() && j == numberOfRows() - 1) {
56  }
57  Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j));
58  KDCoordinate defaultHeight = sequence->type() == Sequence::Type::Explicit ? Metric::StoreRowHeight : k_emptySubRowHeight;
59  ExpressionLayout * layout = sequence->layout();
60  if (sequenceDefinitionForRow(j) == 1) {
61  layout = sequence->firstInitialConditionLayout();
62  }
63  if (sequenceDefinitionForRow(j) == 2) {
64  layout = sequence->secondInitialConditionLayout();
65  }
66  if (layout == nullptr) {
67  return defaultHeight;
68  }
69  KDCoordinate sequenceSize = layout->size().height();
70  return sequenceSize + defaultHeight - KDText::charSize().height();
71 }
72 
75  EvenOddCell * myCell = (EvenOddCell *)cell;
76  myCell->setEven(functionIndexForRow(j)%2 == 0);
77 }
78 
80  if (sequenceDefinitionForRow(selectedRow()) >= 0) {
81  selectCellAtLocation(selectedColumn(), selectedRow()-sequenceDefinitionForRow(selectedRow()));
82  }
83 }
84 
85 void ListController::editExpression(Sequence * sequence, int sequenceDefinition, Ion::Events::Event event) {
86  char * initialText = nullptr;
87  char initialTextContent[TextField::maxBufferSize()];
88  if (event == Ion::Events::OK || event == Ion::Events::EXE) {
89  switch (sequenceDefinition) {
90  case 0:
91  strlcpy(initialTextContent, sequence->text(), sizeof(initialTextContent));
92  break;
93  case 1:
94  strlcpy(initialTextContent, sequence->firstInitialConditionText(), sizeof(initialTextContent));
95  break;
96  default:
97  strlcpy(initialTextContent, sequence->secondInitialConditionText(), sizeof(initialTextContent));
98  break;
99  }
100  initialText = initialTextContent;
101  }
102  App * myApp = (App *)app();
103  InputViewController * inputController = myApp->inputViewController();
104  // Invalidate the sequences context cache
105  static_cast<App *>(app())->localContext()->resetCache();
106  switch (sequenceDefinition) {
107  case 0:
108  inputController->edit(this, event, sequence, initialText,
109  [](void * context, void * sender){
110  Sequence * mySequence = (Sequence *)context;
111  InputViewController * myInputViewController = (InputViewController *)sender;
112  const char * textBody = myInputViewController->textBody();
113  mySequence->setContent(textBody);
114  },
115  [](void * context, void * sender){
116  });
117  break;
118  case 1:
119  inputController->edit(this, event, sequence, initialText,
120  [](void * context, void * sender){
121  Sequence * mySequence = (Sequence *)context;
122  InputViewController * myInputViewController = (InputViewController *)sender;
123  const char * textBody = myInputViewController->textBody();
124  mySequence->setFirstInitialConditionContent(textBody);
125  },
126  [](void * context, void * sender){
127  });
128  break;
129  default:
130  inputController->edit(this, event, sequence, initialText,
131  [](void * context, void * sender){
132  Sequence * mySequence = (Sequence *)context;
133  InputViewController * myInputViewController = (InputViewController *)sender;
134  const char * textBody = myInputViewController->textBody();
135  mySequence->setSecondInitialConditionContent(textBody);
136  },
137  [](void * context, void * sender){
138  });
139  }
140 }
141 
142 bool ListController::removeFunctionRow(Function * function) {
143  m_functionStore->removeFunction(function);
144  // Invalidate the sequences context cache
145  static_cast<App *>(app())->localContext()->resetCache();
146  return true;
147 }
148 
149 ListParameterController * ListController::parameterController() {
150  return &m_parameterController;
151 }
152 
153 int ListController::maxNumberOfRows() {
154  return k_maxNumberOfRows;
155 }
156 
157 HighlightCell * ListController::titleCells(int index) {
158  assert(index >= 0 && index < k_maxNumberOfRows);
159  return m_sequenceTitleCells[index];
160 }
161 
162 HighlightCell * ListController::expressionCells(int index) {
163  assert(index >= 0 && index < k_maxNumberOfRows);
164  return m_expressionCells[index];
165 }
166 
167 
168 void ListController::willDisplayTitleCellAtIndex(HighlightCell * cell, int j) {
169  SequenceTitleCell * myCell = (SequenceTitleCell *)cell;
170  Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j));
171  if (sequenceDefinitionForRow(j) == 0) {
172  myCell->setExpression(sequence->definitionName());
173  }
174  if (sequenceDefinitionForRow(j) == 1) {
175  myCell->setExpression(sequence->firstInitialConditionName());
176  }
177  if (sequenceDefinitionForRow(j) == 2) {
178  myCell->setExpression(sequence->secondInitialConditionName());
179  }
180  KDColor nameColor = sequence->isActive() ? sequence->color() : Palette::GreyDark;
181  myCell->setColor(nameColor);
182 }
183 
184 void ListController::willDisplayExpressionCellAtIndex(HighlightCell * cell, int j) {
186  Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(j));
187  if (sequenceDefinitionForRow(j) == 0) {
188  myCell->setExpression(sequence->layout());
189  }
190  if (sequenceDefinitionForRow(j) == 1) {
191  myCell->setExpression(sequence->firstInitialConditionLayout());
192  }
193  if (sequenceDefinitionForRow(j) == 2) {
194  myCell->setExpression(sequence->secondInitialConditionLayout());
195  }
196  bool active = sequence->isActive();
197  KDColor textColor = active ? KDColorBlack : Palette::GreyDark;
198  myCell->setTextColor(textColor);
199 }
200 
201 int ListController::functionIndexForRow(int j) {
202  if (j < 0) {
203  return j;
204  }
205  if (m_sequenceStore->numberOfFunctions() < m_sequenceStore->maxNumberOfFunctions() &&
206  j == numberOfRows() - 1) {
207  return functionIndexForRow(j-1)+1;
208  }
209  int rowIndex = 0;
210  int sequenceIndex = -1;
211  do {
212  sequenceIndex++;
213  Sequence * sequence = m_sequenceStore->functionAtIndex(sequenceIndex);
214  rowIndex += sequence->numberOfElements();
215  } while (rowIndex <= j);
216  return sequenceIndex;
217 }
218 
219 const char * ListController::textForRow(int j) {
220  Sequence * sequence = (Sequence *)m_functionStore->functionAtIndex(functionIndexForRow(j));
221  switch (sequenceDefinitionForRow(j)) {
222  case 0:
223  return sequence->text();
224  case 1:
225  return sequence->firstInitialConditionText();
226  case 2:
227  return sequence->secondInitialConditionText();
228  default:
229  assert(false);
230  return nullptr;
231  }
232 }
233 
234 int ListController::sequenceDefinitionForRow(int j) {
235  if (j < 0) {
236  return j;
237  }
238  if (m_sequenceStore->numberOfFunctions() < m_sequenceStore->maxNumberOfFunctions() &&
239  j == numberOfRows() - 1) {
240  return 0;
241  }
242  int rowIndex = 0;
243  int sequenceIndex = -1;
244  Sequence * sequence = nullptr;
245  do {
246  sequenceIndex++;
247  sequence = m_sequenceStore->functionAtIndex(sequenceIndex);
248  rowIndex += sequence->numberOfElements();
249  } while (rowIndex <= j);
250  return sequence->numberOfElements()-rowIndex+j;
251 }
252 
253 void ListController::addEmptyFunction() {
255 }
256 
257 void ListController::editExpression(Shared::Function * function, Ion::Events::Event event) {
258  Sequence * sequence = (Sequence *)function;
259  editExpression(sequence, sequenceDefinitionForRow(selectedRow()), event);
260 }
261 
262 void ListController::reinitExpression(Shared::Function * function) {
263  // Invalidate the sequences context cache
264  static_cast<App *>(app())->localContext()->resetCache();
265  Sequence * sequence = (Sequence *)function;
266  switch (sequenceDefinitionForRow(selectedRow())) {
267  case 1:
268  if (strlen(sequence->firstInitialConditionText()) == 0) {
269  return;
270  }
271  sequence->setFirstInitialConditionContent("");
272  break;
273  case 2:
274  if (strlen(sequence->secondInitialConditionText()) == 0) {
275  return;
276  }
277  sequence->setSecondInitialConditionContent("");
278  break;
279  default:
280  if (strlen(sequence->text()) == 0) {
281  return;
282  }
283  sequence->setContent("");
284  break;
285  }
287 }
288 
289 View * ListController::loadView() {
290  for (int i = 0; i < k_maxNumberOfRows; i++) {
291  m_sequenceTitleCells[i] = new SequenceTitleCell(FunctionTitleCell::Orientation::VerticalIndicator);
292  m_expressionCells[i] = new FunctionExpressionCell();
293  }
295 }
296 
297 void ListController::unloadView(View * view) {
298  for (int i = 0; i < k_maxNumberOfRows; i++) {
299  delete m_sequenceTitleCells[i];
300  m_sequenceTitleCells[i] = nullptr;
301  delete m_expressionCells[i];
302  m_expressionCells[i] = nullptr;
303  }
305 }
306 
307 }
static constexpr KDCoordinate StoreRowHeight
Definition: metric.h:26
Definition: i18n.h:6
static constexpr KDCoordinate ModalTopMargin
Definition: metric.h:16
void edit(Responder *caller, Ion::Events::Event event, void *context, const char *initialText, Invocation::Action successAction, Invocation::Action failureAction)
#define assert(e)
Definition: assert.h:9
void displayModalViewController(ViewController *vc, float verticalAlignment, float horizontalAlignment, KDCoordinate topMargin=0, KDCoordinate leftMargin=0, KDCoordinate bottomMargin=0, KDCoordinate rightMargin=0)
Definition: app.cpp:85
static constexpr int maxBufferSize()
Definition: text_field.h:23
const Event sequence[]
virtual void setEven(bool even)
static constexpr KDCoordinate CommonRightMargin
Definition: metric.h:9
static constexpr KDCoordinate TabHeight
Definition: metric.h:19
constexpr Event EXE
Definition: events.h:114
int16_t KDCoordinate
Definition: coordinate.h:6
static constexpr KDColor GreyDark
Definition: palette.h:15
Sequence * functionAtIndex(int i) override
int maxNumberOfFunctions() override
size_t strlcpy(char *dst, const char *src, size_t len)
Definition: strlcpy.c:3
static constexpr KDCoordinate ModalBottomMargin
Definition: metric.h:17
void setExtraCells(const char *sequenceName, int recurrenceDepth)
void willDisplayCellAtLocation(HighlightCell *cell, int i, int j) override
FunctionStore * m_functionStore
virtual Function * functionAtIndex(int i)=0
void reloadData(bool setFirstResponder=true)
enum Message uint16_t enum Language uint16_t const char * translate(Message m, Language l=(Language) 0)
Definition: i18n.cpp:5
constexpr KDColor KDColorWhite
Definition: color.h:42
size_t strlen(const char *s)
Definition: strlen.c:3
View * loadView() override
static constexpr KDColor PurpleDark
Definition: palette.h:11
void willDisplayCellAtLocation(HighlightCell *cell, int i, int j) override
constexpr KDColor KDColorBlack
Definition: color.h:41
virtual KDCoordinate rowHeight(int j) override
static constexpr KDCoordinate CommonLeftMargin
Definition: metric.h:8
ListController(Responder *parentResponder, FunctionStore *functionStore, ButtonRowController *header, ButtonRowController *footer, I18n::Message text)
Definition: app.h:23
void unloadView(View *view) override
Definition: color.h:6
Definition: app.cpp:7
const char * title() override
Definition: view.h:23
SelectableTableView * selectableTableView()
static constexpr KDSize charSize(FontSize size=FontSize::Large)
Definition: text.h:16
App * app()
Definition: responder.cpp:77
void setExpression(Poincare::ExpressionLayout *expressionLayout)
constexpr Event OK
Definition: events.h:65
Toolbox * toolboxForTextInput(TextInput *textInput) override
virtual void removeFunction(Function *f)=0
constexpr KDCoordinate height() const
Definition: size.h:11