Numworks Epsilon  1.4.1
Graphing Calculator Operating System
sub_controller.cpp
Go to the documentation of this file.
1 #include "sub_controller.h"
2 #include "../global_preferences.h"
3 #include "../apps_container.h"
4 #include "../../poincare/src/layout/baseline_relative_layout.h"
5 #include "../../poincare/src/layout/string_layout.h"
6 #include <assert.h>
7 #include <cmath>
8 
9 using namespace Poincare;
10 
11 namespace Settings {
12 
13 SubController::SubController(Responder * parentResponder) :
14  ViewController(parentResponder),
15  m_editableCell(&m_selectableTableView, this, m_draftTextBuffer),
16  m_selectableTableView(this),
17  m_messageTreeModel(nullptr)
18 {
19  m_selectableTableView.setTopMargin(k_topBottomMargin);
20  m_selectableTableView.setBottomMargin(k_topBottomMargin);
21  for (int i = 0; i < k_totalNumberOfCell; i++) {
25  }
26  const char text[] = {'a','+', Ion::Charset::IComplex, 'b', ' '};
27  m_complexFormatLayout[0] = new StringLayout(text, sizeof(text));
28  const char base[] = {'r', Ion::Charset::Exponential};
29  const char superscript[] = {Ion::Charset::IComplex, Ion::Charset::SmallTheta, ' '};
30  m_complexFormatLayout[1] = new BaselineRelativeLayout(new StringLayout(base, sizeof(base)), new StringLayout(superscript, sizeof(superscript)), BaselineRelativeLayout::Type::Superscript);
31  for (int i = 0; i < 2; i++) {
32  m_complexFormatCells[i].setExpression(m_complexFormatLayout[i]);
33  }
34  m_editableCell.setMessage(I18n::Message::SignificantFigures);
36 }
37 
39  for (int i = 0; i < 2; i++) {
40  if (m_complexFormatLayout[i]) {
41  delete m_complexFormatLayout[i];
42  m_complexFormatLayout[i] = nullptr;
43  }
44  }
45 }
46 
47 const char * SubController::title() {
48  if (m_messageTreeModel) {
49  return I18n::translate(m_messageTreeModel->label());
50  }
51  return "";
52 }
53 
55  return &m_selectableTableView;
56 }
57 
58 void SubController::didEnterResponderChain(Responder * previousFirstResponder) {
59  if (m_messageTreeModel->label() == I18n::Message::ExamMode) {
60  m_selectableTableView.reloadData();
61  }
62 }
63 
65  selectCellAtLocation(0, valueIndexForPreference(m_messageTreeModel->label()));
66  app()->setFirstResponder(&m_selectableTableView);
67 }
68 
70  /* We hide here the activation hardware test app: in the menu "about", by
71  * clicking on '6' on the last row. */
72  if ((event == Ion::Events::Six || event == Ion::Events::LowerT || event == Ion::Events::UpperT) && m_messageTreeModel->label() == I18n::Message::About && selectedRow() == numberOfRows()-1) {
74  return true;
75  }
76  if (event == Ion::Events::OK || event == Ion::Events::EXE) {
77  /* Behavious of "Exam mode" menu*/
78  if (m_messageTreeModel->label() == I18n::Message::ExamMode) {
80  return false;
81  }
82  AppsContainer * container = (AppsContainer *)(app()->container());
83  container->displayExamModePopUp(true);
84  return true;
85  }
86  /* Behaviour of "About" menu */
87  if (m_messageTreeModel->label() == I18n::Message::About) {
88  if (selectedRow() == 0) {
89  MessageTableCellWithBuffer * myCell = (MessageTableCellWithBuffer *)m_selectableTableView.selectedCell();
90  if (strcmp(myCell->accessoryText(), Ion::patchLevel()) == 0) {
92  return true;
93  }
95  return true;
96  }
97  return false;
98  }
99  /* Generic behaviour of preference menu*/
100  assert(m_messageTreeModel->label() != I18n::Message::DisplayMode || selectedRow() != numberOfRows()-1); // In that case, events OK and EXE are handled by the cell
101  setPreferenceWithValueIndex(m_messageTreeModel->label(), selectedRow());
102  AppsContainer * myContainer = (AppsContainer * )app()->container();
103  myContainer->refreshPreferences();
104  StackViewController * stack = stackController();
105  stack->pop();
106  return true;
107  }
108  if (event == Ion::Events::Left) {
109  stackController()->pop();
110  return true;
111  }
112  return false;
113 }
114 
116  if (m_messageTreeModel) {
117  return m_messageTreeModel->numberOfChildren();
118  }
119  return 0;
120 }
121 
123  if (type == 2) {
124  assert(index == 0);
125  return &m_editableCell;
126  } else if (type == 1) {
127  assert(index >= 0 && index < 2);
128  return &m_complexFormatCells[index];
129  }
130  assert(index >= 0 && index < k_totalNumberOfCell);
131  return &m_cells[index];
132 }
133 
135  switch (type) {
136  case 0:
137  return k_totalNumberOfCell;
138  case 1:
139  return 2;
140  case 2:
141  return 1;
142  default:
143  assert(false);
144  return 0;
145  }
146 }
147 
148 int SubController::typeAtLocation(int i, int j) {
149  if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) {
150  return 1;
151  }
152  if (m_messageTreeModel->label() == I18n::Message::DisplayMode && j == numberOfRows()-1) {
153  return 2;
154  }
155  return 0;
156 }
157 
160 }
161 
163  return rowHeight(0) * j;
164 }
165 
167  KDCoordinate height = rowHeight(0);
168  if (height == 0) {
169  return 0;
170  }
171  return (offsetY - 1) / height;
172 }
173 
175  if (m_messageTreeModel->label() == I18n::Message::ComplexFormat) {
176  return;
177  }
178  /* Number of significants figure row */
179  if (m_messageTreeModel->label() == I18n::Message::DisplayMode && index == numberOfRows()-1) {
181  char buffer[3];
182  Integer(Preferences::sharedPreferences()->numberOfSignificantDigits()).writeTextInBuffer(buffer, 3);
183  myCell->setAccessoryText(buffer);
184  return;
185  }
187  myCell->setMessage(m_messageTreeModel->children(index)->label());
189  myCell->setAccessoryText("");
190  if (m_messageTreeModel->label() == I18n::Message::ExamMode && GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) {
191  myCell->setMessage(I18n::Message::ExamModeActive);
192  }
193  if (m_messageTreeModel->label() == I18n::Message::About) {
195  const char * accessoryMessage = nullptr;
196  char serialNumber[Ion::SerialNumberLength+1];
197  switch (index) {
198  case 0:
199  accessoryMessage = Ion::softwareVersion();
200  break;
201  case 1:
202  Ion::getSerialNumber(serialNumber);
203  accessoryMessage = serialNumber;
204  break;
205  case 2:
206  accessoryMessage = Ion::fccId();
207  break;
208  default:
209  assert(false);
210  break;
211  }
212  myCell->setAccessoryText(accessoryMessage);
213  }
214 }
215 
216 void SubController::setMessageTreeModel(const MessageTree * messageTreeModel) {
217  m_messageTreeModel = (MessageTree *)messageTreeModel;
218 }
219 
221  m_selectableTableView.reloadData();
222 }
223 
225  m_selectableTableView.deselectTable();
226 }
227 
229  return (event == Ion::Events::Up && selectedRow() > 0)
231 }
232 
233 bool SubController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
234  Context * globalContext = textFieldDelegateApp()->localContext();
235  float floatBody = Expression::approximateToScalar<float>(text, *globalContext);
236  if (std::isnan(floatBody) || std::isinf(floatBody)) {
237  floatBody = PrintFloat::k_numberOfPrintedSignificantDigits;
238  }
239  if (floatBody < 1) {
240  floatBody = 1;
241  }
242  if (floatBody > PrintFloat::k_numberOfStoredSignificantDigits) {
243  floatBody = PrintFloat::k_numberOfStoredSignificantDigits;
244  }
245  Preferences::sharedPreferences()->setNumberOfSignificantDigits((char)std::round(floatBody));
246  m_selectableTableView.reloadCellAtLocation(0, selectedRow());
247  if (event == Ion::Events::Up || event == Ion::Events::OK) {
248  m_selectableTableView.handleEvent(event);
249  }
250  return true;
251 }
252 
253 StackViewController * SubController::stackController() const {
255 }
256 
257 void SubController::setPreferenceWithValueIndex(I18n::Message message, int valueIndex) {
258  if (message == I18n::Message::AngleUnit) {
259  Preferences::sharedPreferences()->setAngleUnit((Expression::AngleUnit)valueIndex);
260  }
261  if (message == I18n::Message::DisplayMode) {
262  Preferences::sharedPreferences()->setDisplayMode((PrintFloat::Mode)valueIndex);
263  }
264  if (message == I18n::Message::ComplexFormat) {
265  Preferences::sharedPreferences()->setComplexFormat((Expression::ComplexFormat)valueIndex);
266  }
267 }
268 
269 int SubController::valueIndexForPreference(I18n::Message message) {
270  if (message == I18n::Message::AngleUnit) {
271  return (int)Preferences::sharedPreferences()->angleUnit();
272  }
273  if (message == I18n::Message::DisplayMode) {
274  return (int)Preferences::sharedPreferences()->displayMode();
275  }
276  if (message == I18n::Message::ComplexFormat) {
277  return (int)Preferences::sharedPreferences()->complexFormat();
278  }
279  return 0;
280 }
281 
282 Shared::TextFieldDelegateApp * SubController::textFieldDelegateApp() {
283  return (Shared::TextFieldDelegateApp *)app();
284 }
285 
286 }
void didBecomeFirstResponder() override
void displayExamModePopUp(bool activate)
void setAccessoryText(const char *textBody)
#define assert(e)
Definition: assert.h:9
int writeTextInBuffer(char *buffer, int bufferSize) const
Definition: integer.cpp:545
void displayModalViewController(ViewController *vc, float verticalAlignment, float horizontalAlignment, KDCoordinate topMargin=0, KDCoordinate leftMargin=0, KDCoordinate bottomMargin=0, KDCoordinate rightMargin=0)
Definition: app.cpp:85
#define isinf(x)
Definition: math.h:44
HighlightCell * selectedCell()
void setBottomMargin(KDCoordinate m)
Definition: scroll_view.h:17
constexpr Event EXE
Definition: events.h:114
void willDisplayCellForIndex(HighlightCell *cell, int index) override
int16_t KDCoordinate
Definition: coordinate.h:6
void setMessageTreeModel(const MessageTree *messageTreeModel)
Responder * parentResponder() const
Definition: responder.cpp:12
static constexpr KDColor GreyDark
Definition: palette.h:15
const char * patchLevel()
int reusableCellCount(int type) override
constexpr Event Up
Definition: events.h:62
void setAccessoryFontSize(KDText::FontSize fontSize)
KDCoordinate cumulatedHeightFromIndex(int j) override
int numberOfChildren() const
Definition: message_tree.cpp:3
bool textFieldDidFinishEditing(TextField *textField, const char *text, Ion::Events::Event event) override
HighlightCell * reusableCell(int index, int type) override
virtual Poincare::Context * localContext()
void reloadData(bool setFirstResponder=true)
const char * title() override
enum Message uint16_t enum Language uint16_t const char * translate(Message m, Language l=(Language) 0)
Definition: i18n.cpp:5
void didEnterResponderChain(Responder *previousFirstResponder) override
void setTopMargin(KDCoordinate m)
Definition: scroll_view.h:13
constexpr Event UpperT
Definition: events.h:206
I18n::Message label() const
Definition: message_tree.cpp:7
void reloadCellAtLocation(int i, int j)
Definition: table_view.cpp:49
#define round(x)
Definition: math.h:192
void setExpression(Poincare::ExpressionLayout *expressionLayout)
int typeAtLocation(int i, int j) override
void getSerialNumber(char *buffer)
Definition: device.cpp:77
#define isnan(x)
Definition: math.h:43
const char * fccId()
Definition: fcc_id.cpp:4
void setMessageFontSize(KDText::FontSize fontSize)
constexpr Event Left
Definition: events.h:61
static constexpr KDCoordinate ExamPopUpBottomMargin
Definition: metric.h:25
void setMessage(I18n::Message message)
const Container * container() const
Definition: app.cpp:102
static constexpr KDCoordinate ParameterCellHeight
Definition: metric.h:15
void setFirstResponder(Responder *responder)
Definition: app.cpp:62
Definition: view.h:23
virtual bool textFieldShouldFinishEditing(TextField *textField, Ion::Events::Event event)=0
ExamMode examMode() const
virtual const MessageTree * children(int index) const =0
View * view() override
virtual bool handleEvent(Ion::Events::Event event) override
bool handleEvent(Ion::Events::Event event) override
constexpr Event LowerT
Definition: events.h:169
const char * softwareVersion()
int indexFromCumulatedHeight(KDCoordinate offsetY) override
int strcmp(const char *s1, const char *s2)
Definition: strcmp.c:3
App * app()
Definition: responder.cpp:77
constexpr Event OK
Definition: events.h:65
static constexpr KDCoordinate PopUpRightMargin
Definition: metric.h:22
constexpr Event Six
Definition: events.h:100
void viewWillAppear() override
bool textFieldShouldFinishEditing(TextField *textField, Ion::Events::Event event) override
void viewDidDisappear() override
Definition: app.cpp:5
KDCoordinate rowHeight(int j) override
static GlobalPreferences * sharedGlobalPreferences()
static constexpr KDCoordinate ExamPopUpTopMargin
Definition: metric.h:24
static constexpr KDCoordinate PopUpLeftMargin
Definition: metric.h:21