mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[apps/escher/toolbox] handleEventWithText for all responders.
This makes the code in the various toolbox more generic. The arguments of the text to insert are each replaced by a Ion::Charset::Empty. These Empty chars are used to create layouts in ExpressionLayoutFields, and to compute the position of the cursor in other fields, before being removed. Change-Id: Ie81c1e394b06fef2ab801ccff919d6550f70ec30
This commit is contained in:
@@ -294,8 +294,7 @@ bool PythonToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) {
|
||||
int strippedEditedTextMaxLength = strlen(editedText)+1;
|
||||
char strippedEditedText[strippedEditedTextMaxLength];
|
||||
Shared::ToolboxHelpers::TextToInsertForCommandMessage(node->insertedText(), strippedEditedText, strippedEditedTextMaxLength);
|
||||
TextInput * textInput = static_cast<TextInput *>(sender());
|
||||
textInput->handleEventWithText(strippedEditedText, true);
|
||||
sender()->handleEventWithText(strippedEditedText, true);
|
||||
app()->dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,7 @@ namespace Code {
|
||||
|
||||
class PythonToolbox : public Toolbox {
|
||||
public:
|
||||
typedef void (*Action)(void * sender, const char * text);
|
||||
PythonToolbox();
|
||||
|
||||
// StackViewController
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
protected:
|
||||
KDCoordinate rowHeight(int j) override;
|
||||
|
||||
@@ -108,67 +108,21 @@ const ToolboxMessageTree toolboxModel = ToolboxMessageTree(I18n::Message::Toolbo
|
||||
#endif
|
||||
|
||||
MathToolbox::MathToolbox() :
|
||||
Toolbox(nullptr, I18n::translate(rootModel()->label())),
|
||||
m_action(actionForTextInput)
|
||||
Toolbox(nullptr, I18n::translate(rootModel()->label()))
|
||||
{
|
||||
}
|
||||
|
||||
void MathToolbox::setSenderAndAction(Responder * sender, Action action) {
|
||||
setSender(sender);
|
||||
m_action = action;
|
||||
}
|
||||
|
||||
void MathToolbox::actionForExpressionLayoutField(void * sender, const char * text, bool removeArguments) {
|
||||
ExpressionLayoutField * expressionLayoutEditorSender = static_cast<ExpressionLayoutField *>(sender);
|
||||
Expression * resultExpression = nullptr;
|
||||
if (removeArguments) {
|
||||
// Replace the arguments with Empty chars.
|
||||
int textToInsertMaxLength = strlen(text);
|
||||
char textToInsert[textToInsertMaxLength];
|
||||
Shared::ToolboxHelpers::TextToParseIntoLayoutForCommandText(text, textToInsert, textToInsertMaxLength);
|
||||
// Create the layout
|
||||
resultExpression = Expression::parse(textToInsert);
|
||||
} else {
|
||||
resultExpression = Expression::parse(text);
|
||||
}
|
||||
if (resultExpression == nullptr) {
|
||||
return;
|
||||
}
|
||||
ExpressionLayout * resultLayout = resultExpression->createLayout();
|
||||
// Find the pointed layout.
|
||||
ExpressionLayout * pointedLayout = nullptr;
|
||||
if (resultLayout->isHorizontal()) {
|
||||
// If the layout is horizontal, pick the first open parenthesis.
|
||||
// For now, all horizontal layouts in MathToolbox have parentheses.
|
||||
for (int i = 0; i < resultLayout->numberOfChildren(); i++) {
|
||||
if (resultLayout->editableChild(i)->isLeftParenthesis()) {
|
||||
pointedLayout = resultLayout->editableChild(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Insert the layout. If pointedLayout is nullptr, the cursor will be on the
|
||||
// right of the inserted layout.
|
||||
expressionLayoutEditorSender->insertLayoutAtCursor(resultLayout, pointedLayout);
|
||||
}
|
||||
|
||||
void MathToolbox::actionForTextInput(void * sender, const char * text, bool removeArguments) {
|
||||
TextInput * textInputSender = static_cast<TextInput *>(sender);
|
||||
if (removeArguments) {
|
||||
int maxTextToInsertLength = strlen(text);
|
||||
char textToInsert[maxTextToInsertLength];
|
||||
// Translate the message and remove the arguments.
|
||||
Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength);
|
||||
textInputSender->handleEventWithText(textToInsert);
|
||||
} else {
|
||||
textInputSender->handleEventWithText(text);
|
||||
}
|
||||
}
|
||||
|
||||
bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) {
|
||||
ToolboxMessageTree * messageTree = selectedMessageTree;
|
||||
m_selectableTableView.deselectTable();
|
||||
m_action(sender(), I18n::translate(messageTree->insertedText()), true);
|
||||
|
||||
// Translate the message and remove the arguments
|
||||
const char * text = I18n::translate(messageTree->insertedText());
|
||||
int maxTextToInsertLength = strlen(text) + 1;
|
||||
char textToInsert[maxTextToInsertLength];
|
||||
Shared::ToolboxHelpers::TextToInsertForCommandText(text, textToInsert, maxTextToInsertLength, true);
|
||||
|
||||
sender()->handleEventWithText(textToInsert);
|
||||
app()->dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
|
||||
class MathToolbox : public Toolbox {
|
||||
public:
|
||||
typedef void (*Action)(void * sender, const char * text, bool removeArguments);
|
||||
MathToolbox();
|
||||
void setSenderAndAction(Responder * sender, Action action);
|
||||
static void actionForExpressionLayoutField(void * sender, const char * text, bool removeArguments = true);
|
||||
static void actionForTextInput(void * sender, const char * text, bool removeArguments = true);
|
||||
protected:
|
||||
bool selectLeaf(ToolboxMessageTree * selectedMessageTree) override;
|
||||
const ToolboxMessageTree * rootModel() override;
|
||||
@@ -19,7 +15,6 @@ protected:
|
||||
MessageTableCellWithChevron* nodeCellAtIndex(int index) override;
|
||||
int maxNumberOfDisplayedRows() override;
|
||||
constexpr static int k_maxNumberOfDisplayedRows = 6; // = 240/40
|
||||
Action m_action;
|
||||
private:
|
||||
MessageTableCellWithMessage m_leafCells[k_maxNumberOfDisplayedRows];
|
||||
MessageTableCellWithChevron m_nodeCells[k_maxNumberOfDisplayedRows];
|
||||
|
||||
@@ -24,15 +24,11 @@ const char * ListController::title() {
|
||||
}
|
||||
|
||||
Toolbox * ListController::toolboxForTextInput(TextInput * textInput) {
|
||||
setToolboxExtraCells();
|
||||
m_sequenceToolbox.setSenderAndAction(textInput, MathToolbox::actionForTextInput);
|
||||
return &m_sequenceToolbox;
|
||||
return toolbox(textInput);
|
||||
}
|
||||
|
||||
Toolbox * ListController::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) {
|
||||
setToolboxExtraCells();
|
||||
m_sequenceToolbox.setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField);
|
||||
return &m_sequenceToolbox;
|
||||
return toolbox(expressionLayoutField);
|
||||
}
|
||||
|
||||
TextFieldDelegateApp * ListController::textFieldDelegateApp() {
|
||||
@@ -87,6 +83,20 @@ void ListController::selectPreviousNewSequenceCell() {
|
||||
}
|
||||
}
|
||||
|
||||
Toolbox * ListController::toolbox(Responder * sender) {
|
||||
// Set extra cells
|
||||
int recurrenceDepth = -1;
|
||||
int sequenceDefinition = sequenceDefinitionForRow(selectedRow());
|
||||
Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow()));
|
||||
if (sequenceDefinition == 0) {
|
||||
recurrenceDepth = sequence->numberOfElements()-1;
|
||||
}
|
||||
m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth);
|
||||
// Set sender
|
||||
m_sequenceToolbox.setSender(sender);
|
||||
return &m_sequenceToolbox;
|
||||
}
|
||||
|
||||
void ListController::editExpression(Sequence * sequence, int sequenceDefinition, Ion::Events::Event event) {
|
||||
char * initialText = nullptr;
|
||||
char initialTextContent[TextField::maxBufferSize()];
|
||||
@@ -309,14 +319,4 @@ void ListController::unloadView(View * view) {
|
||||
Shared::ListController::unloadView(view);
|
||||
}
|
||||
|
||||
void ListController::setToolboxExtraCells() {
|
||||
int recurrenceDepth = -1;
|
||||
int sequenceDefinition = sequenceDefinitionForRow(selectedRow());
|
||||
Sequence * sequence = m_sequenceStore->functionAtIndex(functionIndexForRow(selectedRow()));
|
||||
if (sequenceDefinition == 0) {
|
||||
recurrenceDepth = sequence->numberOfElements()-1;
|
||||
}
|
||||
m_sequenceToolbox.setExtraCells(sequence->name(), recurrenceDepth);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
Toolbox * toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) override;
|
||||
void selectPreviousNewSequenceCell();
|
||||
private:
|
||||
Toolbox * toolbox(Responder * sender);
|
||||
Shared::TextFieldDelegateApp * textFieldDelegateApp() override;
|
||||
Shared::ExpressionFieldDelegateApp * expressionFieldDelegateApp() override;
|
||||
void editExpression(Sequence * sequence, int sequenceDefinitionIndex, Ion::Events::Event event);
|
||||
@@ -44,7 +45,6 @@ private:
|
||||
void reinitExpression(Shared::Function * function) override;
|
||||
View * loadView() override;
|
||||
void unloadView(View * view) override;
|
||||
void setToolboxExtraCells();
|
||||
static constexpr KDCoordinate k_emptySubRowHeight = 30;
|
||||
constexpr static int k_maxNumberOfRows = 3*MaxNumberOfSequences;
|
||||
SequenceStore * m_sequenceStore;
|
||||
|
||||
@@ -114,26 +114,7 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){
|
||||
int bufferSize = 10;
|
||||
char buffer[bufferSize];
|
||||
m_addedCellLayout[selectedRow]->writeTextInBuffer(buffer, bufferSize);
|
||||
if (m_action == MathToolbox::actionForTextInput) {
|
||||
/* DIRTY. The symbols are layouted using a Subscript VerticalOffsetLayout,
|
||||
* which serializes into "_{}", but we want parentheses for text fields. We
|
||||
* thus need to remove any underscores, and changes brackets into
|
||||
* parentheses. */
|
||||
for (int i = 0; i < bufferSize; i++) {
|
||||
if (buffer[i] == '{') {
|
||||
buffer[i] = '(';
|
||||
}
|
||||
if (buffer[i] == '}') {
|
||||
buffer[i] = ')';
|
||||
}
|
||||
if (buffer[i] == '_') {
|
||||
memmove(&buffer[i], &buffer[i+1], bufferSize - (i+1) + 1);
|
||||
bufferSize--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_action(sender(), buffer, false);
|
||||
sender()->handleEventWithText(buffer);
|
||||
app()->dismissModalViewController();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ bool ExpressionFieldDelegateApp::expressionLayoutFieldDidReceiveEvent(Expression
|
||||
|
||||
Toolbox * ExpressionFieldDelegateApp::toolboxForExpressionLayoutField(ExpressionLayoutField * expressionLayoutField) {
|
||||
Toolbox * toolbox = container()->mathToolbox();
|
||||
static_cast<MathToolbox *>(toolbox)->setSenderAndAction(expressionLayoutField, MathToolbox::actionForExpressionLayoutField);
|
||||
toolbox->setSender(expressionLayoutField);
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion::
|
||||
|
||||
Toolbox * TextFieldDelegateApp::toolboxForTextInput(TextInput * textInput) {
|
||||
Toolbox * toolbox = container()->mathToolbox();
|
||||
static_cast<MathToolbox *>(toolbox)->setSenderAndAction(textInput, MathToolbox::actionForTextInput);
|
||||
toolbox->setSender(textInput);
|
||||
return toolbox;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace Shared {
|
||||
namespace ToolboxHelpers {
|
||||
|
||||
int CursorIndexInCommandText(const char * text) {
|
||||
for (size_t i = 0; i < strlen(text); i++) {
|
||||
size_t textLength = strlen(text);
|
||||
for (size_t i = 0; i < textLength; i++) {
|
||||
if (text[i] == '(' || text[i] == '\'') {
|
||||
return i + 1;
|
||||
}
|
||||
@@ -16,7 +17,7 @@ int CursorIndexInCommandText(const char * text) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return strlen(text);
|
||||
return textLength;
|
||||
}
|
||||
|
||||
void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar) {
|
||||
@@ -65,13 +66,5 @@ void TextToInsertForCommandText(const char * command, char * buffer, int bufferS
|
||||
buffer[currentNewTextIndex] = 0;
|
||||
}
|
||||
|
||||
void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize) {
|
||||
TextToParseIntoLayoutForCommandText(I18n::translate(message), buffer, bufferSize);
|
||||
}
|
||||
|
||||
void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize) {
|
||||
TextToInsertForCommandText(command, buffer, bufferSize, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,6 @@ void TextToInsertForCommandMessage(I18n::Message message, char * buffer, int buf
|
||||
void TextToInsertForCommandText(const char * command, char * buffer, int bufferSize, bool replaceArgsWithEmptyChar = false);
|
||||
/* Removes the arguments from a command:
|
||||
* - Removes text between parentheses or brackets, except commas */
|
||||
void TextToParseIntoLayoutForCommandMessage(I18n::Message message, char * buffer, int bufferSize);
|
||||
void TextToParseIntoLayoutForCommandText(const char * command, char * buffer, int bufferSize);
|
||||
/* Removes the arguments from a command and replaces them with empty chars. */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <escher/text_field_delegate.h>
|
||||
#include <poincare/expression_layout.h>
|
||||
|
||||
class ExpressionField : public Responder, public View {
|
||||
class ExpressionField : public Responder, public View {
|
||||
public:
|
||||
ExpressionField(Responder * parentResponder, char * textBuffer, int textBufferLength, Poincare::ExpressionLayout * layout, TextFieldDelegate * textFieldDelegate, ExpressionLayoutFieldDelegate * expressionLayoutFieldDelegate);
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
bool editionIsInTextField() const;
|
||||
bool isEmpty() const;
|
||||
bool heightIsMaximal() const;
|
||||
bool handleEventWithText(const char * text, bool indentation = false) override;
|
||||
|
||||
/* View */
|
||||
int numberOfSubviews() const override { return 1; }
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
void reload();
|
||||
bool hasText() const;
|
||||
void writeTextInBuffer(char * buffer, int bufferLength);
|
||||
bool handleEventWithText(const char * text, bool indentation = false);
|
||||
Poincare::ExpressionLayout * expressionLayout();
|
||||
|
||||
/* Responder */
|
||||
|
||||
@@ -10,6 +10,7 @@ class Responder {
|
||||
public:
|
||||
Responder(Responder * parentResponder);
|
||||
virtual bool handleEvent(Ion::Events::Event event); // Default implementation does nothing
|
||||
virtual bool handleEventWithText(const char * text, bool indentation = false) { return false; }
|
||||
virtual void didBecomeFirstResponder();
|
||||
virtual void willResignFirstResponder();
|
||||
virtual void didEnterResponderChain(Responder * previousFirstResponder);
|
||||
|
||||
@@ -19,7 +19,6 @@ public:
|
||||
size_t cursorLocation() const { return nonEditableContentView()->cursorLocation(); }
|
||||
bool setCursorLocation(int location);
|
||||
virtual void scrollToCursor();
|
||||
virtual bool handleEventWithText(const char * text, bool indenting = false) = 0;
|
||||
protected:
|
||||
class ContentView : public View {
|
||||
public:
|
||||
|
||||
@@ -8,12 +8,9 @@ namespace TextInputHelpers {
|
||||
int CursorIndexInCommand(const char * text);
|
||||
/* Returns the index of the cursor position in a Command, which is the smallest
|
||||
* index between :
|
||||
* - After the first open parenthesis/quote if the following element is
|
||||
* either a quote, a coma or a parenthesi
|
||||
* - The end of the text
|
||||
* - Special case: when the text preceding the parenthesis is 'random', the
|
||||
* cursor position is the end of the text. */
|
||||
constexpr static const char * k_random = "random";
|
||||
* - The first EmptyChar index (which is the position of the first argument)
|
||||
* - The first empty quote
|
||||
* - The end of the text */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
class Toolbox : public StackViewController, public ListViewDataSource, public SelectableTableViewDataSource {
|
||||
public:
|
||||
Toolbox(Responder * parentResponder, const char * title = 0);
|
||||
void setSender(Responder * sender);
|
||||
void setSender(Responder * sender) { m_sender = sender; }
|
||||
|
||||
// StackViewController
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
@@ -72,7 +72,7 @@ protected:
|
||||
bool handleEventForRow(Ion::Events::Event event, int selectedRow);
|
||||
bool selectSubMenu(ToolboxMessageTree * selectedMessageTree);
|
||||
bool returnToPreviousMenu();
|
||||
virtual Responder * sender();
|
||||
Responder * sender() { return m_sender; }
|
||||
virtual bool selectLeaf(ToolboxMessageTree * selectedMessageTree) = 0;
|
||||
virtual const ToolboxMessageTree * rootModel() = 0;
|
||||
virtual MessageTableCellWithMessage * leafCellAtIndex(int index) = 0;
|
||||
|
||||
@@ -109,6 +109,14 @@ bool ExpressionField::heightIsMaximal() const {
|
||||
return inputViewHeight() == k_separatorThickness + k_verticalExpressionViewMargin + maximalHeight();
|
||||
}
|
||||
|
||||
bool ExpressionField::handleEventWithText(const char * text, bool indentation) {
|
||||
if (editionIsInTextField()) {
|
||||
return m_textField.handleEventWithText(text, indentation);
|
||||
} else {
|
||||
return m_expressionLayoutField.handleEventWithText(text, indentation);
|
||||
}
|
||||
}
|
||||
|
||||
KDCoordinate ExpressionField::inputViewHeight() const {
|
||||
if (editionIsInTextField()) {
|
||||
return k_separatorThickness + k_textFieldHeight;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#include <escher/expression_layout_field.h>
|
||||
#include <escher/clipboard.h>
|
||||
#include <escher/text_field.h>
|
||||
#include <poincare/src/layout/matrix_layout.h>
|
||||
#include <poincare/expression.h>
|
||||
#include <poincare/expression_layout_cursor.h>
|
||||
#include <poincare/src/layout/matrix_layout.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
ExpressionLayoutField::ExpressionLayoutField(Responder * parentResponder, Poincare::ExpressionLayout * expressionLayout, ExpressionLayoutFieldDelegate * delegate) :
|
||||
ScrollableView(parentResponder, &m_contentView, this),
|
||||
@@ -254,6 +256,47 @@ void ExpressionLayoutField::writeTextInBuffer(char * buffer, int bufferLength) {
|
||||
m_contentView.expressionView()->expressionLayout()->writeTextInBuffer(buffer, bufferLength);
|
||||
}
|
||||
|
||||
bool ExpressionLayoutField::handleEventWithText(const char * text, bool indentation) {
|
||||
size_t textLength = strlen(text) + 1;
|
||||
size_t textToInsertMaxLength = 2*textLength;
|
||||
char textToInsert[textToInsertMaxLength];
|
||||
|
||||
size_t textToInsertIndex = 0;
|
||||
// Add empty chars where arguments are needed
|
||||
for (size_t i = textToInsertIndex; i < textLength; i++) {
|
||||
textToInsert[textToInsertIndex++] = text[i];
|
||||
if (((text[i] == '(' || text[i] == '[')
|
||||
&& text[i+1] == ',')
|
||||
|| (text[i] == ','
|
||||
&& (text[i+1] == ')' || text[i+1] == ']')))
|
||||
{
|
||||
textToInsert[textToInsertIndex++] = Ion::Charset::Empty;
|
||||
}
|
||||
}
|
||||
|
||||
Poincare::Expression * resultExpression = Poincare::Expression::parse(textToInsert);
|
||||
if (resultExpression == nullptr) {
|
||||
return false;
|
||||
}
|
||||
Poincare::ExpressionLayout * resultLayout = resultExpression->createLayout();
|
||||
// Find the pointed layout.
|
||||
Poincare::ExpressionLayout * pointedLayout = nullptr;
|
||||
if (resultLayout->isHorizontal()) {
|
||||
/* If the layout is horizontal, pick the first open parenthesis. For now,
|
||||
* all horizontal layouts in MathToolbox have parentheses. */
|
||||
for (int i = 0; i < resultLayout->numberOfChildren(); i++) {
|
||||
if (resultLayout->editableChild(i)->isLeftParenthesis()) {
|
||||
pointedLayout = resultLayout->editableChild(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Insert the layout. If pointedLayout is nullptr, the cursor will be on the
|
||||
* right of the inserted layout. */
|
||||
insertLayoutAtCursor(resultLayout, pointedLayout);
|
||||
return true;
|
||||
}
|
||||
|
||||
Poincare::ExpressionLayout * ExpressionLayoutField::expressionLayout() {
|
||||
return m_contentView.expressionView()->expressionLayout();
|
||||
}
|
||||
|
||||
@@ -293,8 +293,22 @@ TextArea::TextArea(Responder * parentResponder, char * textBuffer,
|
||||
|
||||
bool TextArea::handleEventWithText(const char * text, bool indentation) {
|
||||
int nextCursorLocation = cursorLocation();
|
||||
if ((indentation && insertTextWithIndentation(text, cursorLocation())) || insertTextAtLocation(text, cursorLocation())) {
|
||||
nextCursorLocation += TextInputHelpers::CursorIndexInCommand(text);
|
||||
|
||||
int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(text);
|
||||
|
||||
size_t eventTextSize = strlen(text) + 1;
|
||||
char buffer[eventTextSize];
|
||||
size_t bufferIndex = 0;
|
||||
|
||||
// Remove EmptyChars
|
||||
for (size_t i = bufferIndex; i < eventTextSize; i++) {
|
||||
if (text[i] != Ion::Charset::Empty) {
|
||||
buffer[bufferIndex++] = text[i];
|
||||
}
|
||||
}
|
||||
|
||||
if ((indentation && insertTextWithIndentation(buffer, cursorLocation())) || insertTextAtLocation(buffer, cursorLocation())) {
|
||||
nextCursorLocation += cursorIndexInCommand;
|
||||
}
|
||||
setCursorLocation(nextCursorLocation);
|
||||
return true;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <escher/text_field.h>
|
||||
#include <escher/text_input_helpers.h>
|
||||
#include <escher/clipboard.h>
|
||||
#include <ion/charset.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* TextField::ContentView */
|
||||
@@ -305,12 +306,41 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation) {
|
||||
if (!isEditing()) {
|
||||
setEditing(true);
|
||||
}
|
||||
size_t eventTextSize = strlen(eventText) + 1;
|
||||
char buffer[eventTextSize];
|
||||
size_t bufferIndex = 0;
|
||||
|
||||
/* DIRTY
|
||||
* We use the notation "_{}" to indicate a subscript layout. In a text field,
|
||||
* such a subscript should be written using parentheses. For instance: "u_{n}"
|
||||
* should be inserted as "u(n)".
|
||||
* We thus remove underscores and changes brackets into parentheses. */
|
||||
for (size_t i = bufferIndex; i < eventTextSize; i++) {
|
||||
if (eventText[i] == '{') {
|
||||
buffer[bufferIndex++] = '(';
|
||||
} else if (eventText[i] == '}') {
|
||||
buffer[bufferIndex++] = ')';
|
||||
} else if (eventText[i] != '_') {
|
||||
buffer[bufferIndex++] = eventText[i];
|
||||
}
|
||||
}
|
||||
|
||||
int cursorIndexInCommand = TextInputHelpers::CursorIndexInCommand(eventText);
|
||||
|
||||
bufferIndex = 0;
|
||||
// Remove EmptyChars
|
||||
for (size_t i = bufferIndex; i < eventTextSize; i++) {
|
||||
if (buffer[i] != Ion::Charset::Empty) {
|
||||
buffer[bufferIndex++] = buffer[i];
|
||||
}
|
||||
}
|
||||
|
||||
int nextCursorLocation = draftTextLength();
|
||||
if (insertTextAtLocation(eventText, cursorLocation())) {
|
||||
/* The cursor position depends on the text as we sometimes want to
|
||||
* position the cursor at the end of the text and sometimes after the
|
||||
* first parenthesis. */
|
||||
nextCursorLocation = cursorLocation() + TextInputHelpers::CursorIndexInCommand(eventText);
|
||||
if (insertTextAtLocation(buffer, cursorLocation())) {
|
||||
/* The cursor position depends on the text as we sometimes want to position
|
||||
* the cursor at the end of the text and sometimes after the first
|
||||
* parenthesis. */
|
||||
nextCursorLocation = cursorLocation() + cursorIndexInCommand;
|
||||
}
|
||||
setCursorLocation(nextCursorLocation);
|
||||
return m_delegate->textFieldDidHandleEvent(this, true, strlen(text()) != previousTextLength);
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
#include <escher/text_input_helpers.h>
|
||||
#include <ion/charset.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace TextInputHelpers {
|
||||
|
||||
int CursorIndexInCommand(const char * text) {
|
||||
for (size_t i = 0; i < strlen(text)-1; i++) {
|
||||
if (text[i] == '(' || text[i] == '\'') {
|
||||
if (text[i+1] == ')' || text[i+1] == '\'' || text[i+1] == ',') {
|
||||
if (i >= strlen(k_random) && memcmp(&text[i-strlen(k_random)], k_random, strlen(k_random)) == 0) {
|
||||
break;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
size_t textLength = strlen(text);
|
||||
for (size_t i = 0; i < textLength - 1; i++) {
|
||||
if (text[i] == '\'' && text[i+1] == '\'') {
|
||||
return i + 1;
|
||||
} else if (text[i] == Ion::Charset::Empty) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return strlen(text);
|
||||
return textLength;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -94,10 +94,6 @@ Toolbox::Toolbox(Responder * parentResponder, const char * title) :
|
||||
{
|
||||
}
|
||||
|
||||
void Toolbox::setSender(Responder * sender) {
|
||||
m_sender = sender;
|
||||
}
|
||||
|
||||
bool Toolbox::handleEvent(Ion::Events::Event event) {
|
||||
return handleEventForRow(event, selectedRow());
|
||||
}
|
||||
@@ -232,7 +228,3 @@ bool Toolbox::returnToPreviousMenu() {
|
||||
app()->setFirstResponder(&m_listController);
|
||||
return true;
|
||||
}
|
||||
|
||||
Responder * Toolbox::sender() {
|
||||
return m_sender;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user