mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 08:47:28 +01:00
A boolean in ViewController states if the ViewController wants MaximumSpace (do not show any stack view headers), or if it does not want to add its own title to the stack view headers. If the ViewController's title is null, it is not added to the stack view headers. By default, ButtonRowControllers do not want to add their title (because they are only used for now in TabViews, where the title is already displayed in the tab). Change-Id: I9e4c64b845262e4d44eb03cf769950f9c9e67a3a
303 lines
9.6 KiB
C++
303 lines
9.6 KiB
C++
#include "variable_box_controller.h"
|
|
#include "constant.h"
|
|
#include <assert.h>
|
|
|
|
using namespace Poincare;
|
|
|
|
/* ContentViewController */
|
|
|
|
VariableBoxController::ContentViewController::ContentViewController(Responder * parentResponder, GlobalContext * context) :
|
|
ViewController(parentResponder),
|
|
m_context(context),
|
|
m_firstSelectedRow(0),
|
|
m_previousSelectedRow(0),
|
|
m_currentPage(Page::RootMenu),
|
|
m_selectableTableView(this, this, 0, 1, 0, 0, 0, 0, this, nullptr, false)
|
|
{
|
|
}
|
|
|
|
const char * VariableBoxController::ContentViewController::title() {
|
|
return I18n::translate(I18n::Message::Variables);
|
|
}
|
|
|
|
View * VariableBoxController::ContentViewController::view() {
|
|
return &m_selectableTableView;
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::didBecomeFirstResponder() {
|
|
m_selectableTableView.reloadData();
|
|
m_selectableTableView.scrollToCell(0,0);
|
|
selectCellAtLocation(0, m_firstSelectedRow);
|
|
app()->setFirstResponder(&m_selectableTableView);
|
|
}
|
|
|
|
bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Event event) {
|
|
#if MATRIX_VARIABLES
|
|
if (event == Ion::Events::Back && m_currentPage == Page::RootMenu) {
|
|
#else
|
|
if (event == Ion::Events::Back && m_currentPage == Page::Scalar) {
|
|
#endif
|
|
m_firstSelectedRow = 0;
|
|
app()->dismissModalViewController();
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::Back || event == Ion::Events::Left) {
|
|
m_firstSelectedRow = m_previousSelectedRow;
|
|
#if MATRIX_VARIABLES
|
|
m_selectableTableView.deselectTable();
|
|
m_currentPage = Page::RootMenu;
|
|
#endif
|
|
app()->setFirstResponder(this);
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::OK || event == Ion::Events::EXE || (event == Ion::Events::Right && m_currentPage == Page::RootMenu)) {
|
|
if (m_currentPage == Page::RootMenu) {
|
|
m_previousSelectedRow = selectedRow();
|
|
m_firstSelectedRow = 0;
|
|
m_selectableTableView.deselectTable();
|
|
m_currentPage = pageAtIndex(m_previousSelectedRow);
|
|
app()->setFirstResponder(this);
|
|
return true;
|
|
}
|
|
m_firstSelectedRow = 0;
|
|
char label[3];
|
|
putLabelAtIndexInBuffer(selectedRow(), label);
|
|
const char * editedText = label;
|
|
if (!m_textFieldCaller->isEditing()) {
|
|
m_textFieldCaller->setEditing(true);
|
|
}
|
|
m_textFieldCaller->insertTextAtLocation(editedText, m_textFieldCaller->cursorLocation());
|
|
m_textFieldCaller->setCursorLocation(m_textFieldCaller->cursorLocation() + strlen(editedText));
|
|
#if MATRIX_VARIABLES
|
|
m_selectableTableView.deselectTable();
|
|
m_currentPage = Page::RootMenu;
|
|
#endif
|
|
app()->dismissModalViewController();
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::Backspace && m_currentPage != Page::RootMenu) {
|
|
if (m_currentPage == Page::Scalar) {
|
|
const Symbol symbol = Symbol('A'+selectedRow());
|
|
m_context->setExpressionForSymbolName(nullptr, &symbol);
|
|
}
|
|
if (m_currentPage == Page::Matrix) {
|
|
const Symbol symbol = Symbol::matrixSymbol('0'+(char)selectedRow());
|
|
m_context->setExpressionForSymbolName(nullptr, &symbol);
|
|
}
|
|
m_selectableTableView.reloadData();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int VariableBoxController::ContentViewController::numberOfRows() {
|
|
switch (m_currentPage) {
|
|
case Page::RootMenu:
|
|
return k_numberOfMenuRows;
|
|
case Page::Scalar:
|
|
return GlobalContext::k_maxNumberOfScalarExpressions;
|
|
#if LIST_VARIABLES
|
|
case Page::List:
|
|
return GlobalContext::k_maxNumberOfListExpressions;
|
|
#endif
|
|
case Page::Matrix:
|
|
return GlobalContext::k_maxNumberOfMatrixExpressions;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
HighlightCell * VariableBoxController::ContentViewController::reusableCell(int index, int type) {
|
|
assert(type < 2);
|
|
assert(index >= 0);
|
|
if (type == 0) {
|
|
assert(index < k_maxNumberOfDisplayedRows);
|
|
return &m_leafCells[index];
|
|
}
|
|
assert(index < k_numberOfMenuRows);
|
|
return &m_nodeCells[index];
|
|
}
|
|
|
|
int VariableBoxController::ContentViewController::reusableCellCount(int type) {
|
|
assert(type < 2);
|
|
if (type == 0) {
|
|
return k_maxNumberOfDisplayedRows;
|
|
}
|
|
return k_numberOfMenuRows;
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
|
if (m_currentPage == Page::RootMenu) {
|
|
I18n::Message label = nodeLabelAtIndex(index);
|
|
MessageTableCell * myCell = (MessageTableCell *)cell;
|
|
myCell->setMessage(label);
|
|
return;
|
|
}
|
|
VariableBoxLeafCell * myCell = (VariableBoxLeafCell *)cell;
|
|
char label[3];
|
|
putLabelAtIndexInBuffer(index, label);
|
|
myCell->setLabel(label);
|
|
const Evaluation<double> * evaluation = expressionForIndex(index);
|
|
if (m_currentPage == Page::Scalar) {
|
|
myCell->displayExpression(false);
|
|
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
|
|
evaluation->writeTextInBuffer(buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits));
|
|
myCell->setSubtitle(buffer);
|
|
return;
|
|
}
|
|
myCell->displayExpression(true);
|
|
if (evaluation) {
|
|
/* TODO: implement list contexts */
|
|
myCell->setExpression(evaluation);
|
|
char buffer[2*PrintFloat::bufferSizeForFloatsWithPrecision(2)+1];
|
|
int numberOfChars = Complex<float>::convertFloatToText(evaluation->numberOfRows(), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal);
|
|
buffer[numberOfChars++] = 'x';
|
|
Complex<float>::convertFloatToText(evaluation->numberOfColumns(), buffer+numberOfChars, PrintFloat::bufferSizeForFloatsWithPrecision(2), 2, Expression::FloatDisplayMode::Decimal);
|
|
myCell->setSubtitle(buffer);
|
|
} else {
|
|
myCell->setExpression(nullptr);
|
|
myCell->setSubtitle(I18n::translate(I18n::Message::Empty));
|
|
}
|
|
}
|
|
|
|
KDCoordinate VariableBoxController::ContentViewController::rowHeight(int index) {
|
|
if (m_currentPage == Page::RootMenu) {
|
|
return k_nodeRowHeight;
|
|
}
|
|
if (m_currentPage == Page::Scalar) {
|
|
return k_leafRowHeight;
|
|
}
|
|
const Evaluation<double> * expression = expressionForIndex(index);
|
|
if (expression) {
|
|
ExpressionLayout * layout = expression->createLayout();
|
|
KDCoordinate expressionHeight = layout->size().height();
|
|
delete layout;
|
|
return expressionHeight+k_leafMargin;
|
|
}
|
|
return k_leafRowHeight;
|
|
}
|
|
|
|
KDCoordinate VariableBoxController::ContentViewController::cumulatedHeightFromIndex(int j) {
|
|
int result = 0;
|
|
for (int k = 0; k < j; k++) {
|
|
result += rowHeight(k);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int VariableBoxController::ContentViewController::indexFromCumulatedHeight(KDCoordinate offsetY) {
|
|
int result = 0;
|
|
int j = 0;
|
|
while (result < offsetY && j < numberOfRows()) {
|
|
result += rowHeight(j++);
|
|
}
|
|
return (result < offsetY || offsetY == 0) ? j : j - 1;
|
|
}
|
|
|
|
int VariableBoxController::ContentViewController::typeAtLocation(int i, int j) {
|
|
if (m_currentPage == Page::RootMenu) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const Evaluation<double> * VariableBoxController::ContentViewController::expressionForIndex(int index) {
|
|
if (m_currentPage == Page::Scalar) {
|
|
const Symbol symbol = Symbol('A'+index);
|
|
return m_context->evaluationForSymbol(&symbol);
|
|
}
|
|
if (m_currentPage == Page::Matrix) {
|
|
const Symbol symbol = Symbol::matrixSymbol('0'+(char)index);
|
|
return m_context->evaluationForSymbol(&symbol);
|
|
}
|
|
#if LIST_VARIABLES
|
|
if (m_currentPage == Page::List) {
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
return nullptr;
|
|
}
|
|
|
|
VariableBoxController::ContentViewController::Page VariableBoxController::ContentViewController::pageAtIndex(int index) {
|
|
#if LIST_VARIABLES
|
|
Page pages[3] = {Page::Scalar, Page::List, Page::Matrix};
|
|
#else
|
|
Page pages[2] = {Page::Scalar, Page::Matrix};
|
|
#endif
|
|
return pages[index];
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::putLabelAtIndexInBuffer(int index, char * buffer) {
|
|
if (m_currentPage == Page::Scalar) {
|
|
buffer[0] = 'A' + index;
|
|
buffer[1] = 0;
|
|
}
|
|
#if LIST_VARIABLES
|
|
if (m_currentPage == Page::List) {
|
|
buffer[0] = 'L';
|
|
buffer[1] = '0' + index;
|
|
buffer[2] = 0;
|
|
}
|
|
#endif
|
|
if (m_currentPage == Page::Matrix) {
|
|
buffer[0] = 'M';
|
|
buffer[1] = '0' + index;
|
|
buffer[2] = 0;
|
|
}
|
|
}
|
|
|
|
I18n::Message VariableBoxController::ContentViewController::nodeLabelAtIndex(int index) {
|
|
assert(m_currentPage == Page::RootMenu);
|
|
#if LIST_VARIABLES
|
|
I18n::Message labels[3] = {I18n::Message::Number, I18n::Message::List, I18n::Message::Matrix};
|
|
#else
|
|
I18n::Message labels[2] = {I18n::Message::Number, I18n::Message::Matrix};
|
|
#endif
|
|
return labels[index];
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::setTextFieldCaller(TextField * textField) {
|
|
m_textFieldCaller = textField;
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::reloadData() {
|
|
m_selectableTableView.reloadData();
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::resetPage() {
|
|
#if MATRIX_VARIABLES
|
|
m_currentPage = Page::RootMenu;
|
|
#else
|
|
m_currentPage = Page::Scalar;
|
|
#endif
|
|
}
|
|
|
|
void VariableBoxController::ContentViewController::viewDidDisappear() {
|
|
m_selectableTableView.deselectTable();
|
|
ViewController::viewDidDisappear();
|
|
}
|
|
|
|
VariableBoxController::VariableBoxController(GlobalContext * context) :
|
|
StackViewController(nullptr, &m_contentViewController, KDColorWhite, Palette::PurpleBright, Palette::PurpleDark),
|
|
m_contentViewController(this, context)
|
|
{
|
|
}
|
|
|
|
void VariableBoxController::didBecomeFirstResponder() {
|
|
app()->setFirstResponder(&m_contentViewController);
|
|
}
|
|
|
|
void VariableBoxController::setTextFieldCaller(TextField * textField) {
|
|
m_contentViewController.setTextFieldCaller(textField);
|
|
}
|
|
|
|
void VariableBoxController::viewWillAppear() {
|
|
StackViewController::viewWillAppear();
|
|
m_contentViewController.resetPage();
|
|
m_contentViewController.reloadData();
|
|
}
|
|
|
|
void VariableBoxController::viewDidDisappear() {
|
|
StackViewController::viewDidDisappear();
|
|
}
|