[apps][escher] Add methods 'handleEventWithText' in TextField and

TextArea to fix bug in probability (adding a toolbox text from the
calculations controller)
This commit is contained in:
Émilie Feral
2018-02-19 11:18:58 +01:00
committed by EmilieNumworks
parent 7fcf77ce23
commit 576caa039f
24 changed files with 144 additions and 147 deletions

View File

@@ -61,8 +61,7 @@ const char * EditExpressionController::textBody() {
void EditExpressionController::insertTextBody(const char * text) {
TextField * tf = ((ContentView *)view())->textField();
tf->setEditing(true, false);
tf->insertTextAtLocation(text, tf->cursorLocation());
tf->setCursorLocation(tf->cursorLocation() + strlen(text));
tf->handleEventWithText(text);
}
bool EditExpressionController::handleEvent(Ion::Events::Event event) {

View File

@@ -13,9 +13,7 @@ bool TextField::handleEvent(Ion::Events::Event event) {
return false;
}
if (event == Ion::Events::Ans) {
insertTextAtLocation("ans", cursorLocation());
setCursorLocation(cursorLocation() + strlen("ans"));
return true;
return handleEventWithText("ans");
}
if (isEditing() && draftTextLength() == 0 &&
(event == Ion::Events::Multiplication ||
@@ -24,8 +22,7 @@ bool TextField::handleEvent(Ion::Events::Event event) {
event == Ion::Events::Square ||
event == Ion::Events::Division ||
event == Ion::Events::Sto)) {
insertTextAtLocation("ans", cursorLocation());
setCursorLocation(cursorLocation() + strlen("ans"));
handleEventWithText("ans");
}
return(::TextField::handleEvent(event));
}

View File

@@ -1,7 +1,6 @@
#include "app.h"
#include "../apps_container.h"
#include "code_icon.h"
#include "../shared/toolbox_helpers.h"
#include "../i18n.h"
namespace Code {
@@ -80,27 +79,12 @@ App::App(Container * container, Snapshot * snapshot) :
m_codeStackViewController(&m_modalViewController, &m_listFooter),
m_toolboxActionForTextArea([](void * sender, const char * text) {
TextArea * textArea = static_cast<TextArea *>(sender);
int previousCursorLocation = textArea->cursorLocation();
if (textArea->insertTextWithIndentation(text)) {
// insertText() also moves the cursor. We need to re-move it to the
// position we want (which is after the first parenthesis or before the
// first point).
int deltaCursorLocation = - textArea->cursorLocation() + previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommand(text);
// WARNING: This is a dirty and only works because the cursor location we
// want is always on the first line of the text we insert. Because of the
// auto indentation, it would be difficult to compute the wanted cursor
// location on other lines of the text.
textArea->moveCursor(deltaCursorLocation);
}}),
textArea->handleEventWithText(text, true);
}),
m_toolboxActionForTextField([](void * sender, const char * text) {
TextField * textField = static_cast<TextField *>(sender);
if (!textField->isEditing()) {
textField->setEditing(true);
}
int newCursorLocation = textField->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(text);
if (textField->insertTextAtLocation(text, textField->cursorLocation())) {
textField->setCursorLocation(newCursorLocation);
}}),
textField->handleEventWithText(text);
}),
m_variableBoxController(&m_menuController, snapshot->scriptStore())
{
}

View File

@@ -276,12 +276,7 @@ bool ConsoleController::textFieldDidReceiveEvent(TextField * textField, Ion::Eve
if (pythonText == nullptr) {
return false;
}
if (textField->insertTextAtLocation(pythonText, textField->cursorLocation())) {
textField->setCursorLocation(textField->cursorLocation()+strlen(pythonText));
if (pythonText[strlen(pythonText)-1] == ')') {
textField->setCursorLocation(textField->cursorLocation()-1);
}
}
textField->handleEventWithText(pythonText);
return true;
}

View File

@@ -52,10 +52,7 @@ void ConsoleEditCell::setPrompt(const char * prompt) {
}
bool ConsoleEditCell::insertText(const char * text) {
bool didCopy = m_textField.insertTextAtLocation(text, m_textField.cursorLocation());
if (didCopy) {
m_textField.setCursorLocation(m_textField.cursorLocation() + strlen(text));
}
return didCopy;
}
return m_textField.handleEventWithText(text);
}
}

View File

@@ -33,7 +33,7 @@ void EditorController::didBecomeFirstResponder() {
}
void EditorController::viewWillAppear() {
m_textArea.moveCursor(strlen(m_textArea.text() - m_textArea.cursorLocation()));
m_textArea.setCursorLocation(strlen(m_textArea.text()));
}
void EditorController::viewDidDisappear() {
@@ -47,12 +47,7 @@ bool EditorController::textAreaShouldFinishEditing(TextArea * textArea, Ion::Eve
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
const char * pythonText = Helpers::PythonTextForEvent(event);
if (pythonText != nullptr) {
if (!textArea->insertText(pythonText)) {
return false;
}
if (pythonText[strlen(pythonText)-1] == ')') {
textArea->moveCursor(-1);
}
textArea->handleEventWithText(pythonText);
return true;
}
@@ -84,10 +79,13 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
indentationIndex++;
}
}
textArea->insertText("\n");
char indentationBuffer[indentationSize+2]; // FIXME
indentationBuffer[0] = '\n';
for (int i = 0; i < indentationSize; i++) {
textArea->insertText(" ");
indentationBuffer[i+1] = ' ';
}
indentationBuffer[indentationSize+1] = 0;
textArea->handleEventWithText(indentationBuffer);
return true;
}
@@ -118,9 +116,12 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
charBeforeCursorIndex--;
}
if (charBeforeCursorIndex >= 0 && text[charBeforeCursorIndex] == '\n') {
char indentationBuffer[k_indentationSpacesNumber+1];
for (int i = 0; i < k_indentationSpacesNumber; i++) {
textArea->insertText(" ");
indentationBuffer[i] = ' ';
}
indentationBuffer[k_indentationSpacesNumber] = 0;
textArea->handleEventWithText(indentationBuffer);
return true;
}
}

View File

@@ -336,7 +336,7 @@ bool MenuController::textFieldDidAbortEditing(TextField * textField, const char
return true;
}
bool MenuController::textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) {
bool MenuController::textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textHasChanged) {
int scriptExtensionLength = strlen(ScriptStore::k_scriptExtension);
if (textField->isEditing() && textField->cursorLocation() > textField->draftTextLength() - scriptExtensionLength) {
textField->setCursorLocation(textField->draftTextLength() - scriptExtensionLength);

View File

@@ -57,7 +57,7 @@ public:
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
bool textFieldDidAbortEditing(TextField * textField, const char * text) override;
bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) override;
bool textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textHasChanged) override;
Toolbox * toolboxForTextField(TextField * textField) override { return nullptr; }
/* ButtonRowDelegate */

View File

@@ -122,19 +122,11 @@ void VariableBoxController::ContentViewController::insertTextInCaller(const char
char commandBuffer[strlen(text)+1];
Shared::ToolboxHelpers::TextToInsertForCommandText(text, commandBuffer);
if (m_textFieldCaller != nullptr) {
if (!m_textFieldCaller->isEditing()) {
m_textFieldCaller->setEditing(true);
}
int previousCursorLocation = m_textFieldCaller->cursorLocation();
m_textFieldCaller->insertTextAtLocation(commandBuffer, previousCursorLocation);
m_textFieldCaller->setCursorLocation(previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommand(commandBuffer));
m_textFieldCaller->handleEventWithText(commandBuffer);
return;
}
if (m_textAreaCaller != nullptr) {
int previousCursorLocation = m_textAreaCaller->cursorLocation();
m_textAreaCaller->insertText(commandBuffer);
int deltaCursorLocation = - m_textAreaCaller->cursorLocation() + previousCursorLocation + Shared::ToolboxHelpers::CursorIndexInCommand(commandBuffer);
m_textAreaCaller->moveCursor(deltaCursorLocation);
m_textAreaCaller->handleEventWithText(commandBuffer);
}
}

View File

@@ -113,14 +113,9 @@ bool MathToolbox::selectLeaf(ToolboxMessageTree * selectedMessageTree) {
m_selectableTableView.deselectTable();
ToolboxMessageTree * messageTree = selectedMessageTree;
const char * editedText = I18n::translate(messageTree->insertedText());
if (!sender()->isEditing()) {
sender()->setEditing(true);
}
char strippedEditedText[strlen(editedText)];
Shared::ToolboxHelpers::TextToInsertForCommandMessage(messageTree->insertedText(), strippedEditedText);
sender()->insertTextAtLocation(strippedEditedText, sender()->cursorLocation());
int newCursorLocation = sender()->cursorLocation() + Shared::ToolboxHelpers::CursorIndexInCommand(strippedEditedText);
sender()->setCursorLocation(newCursorLocation);
sender()->handleEventWithText(strippedEditedText);
app()->dismissModalViewController();
return true;
}

View File

@@ -206,7 +206,7 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
}
}
bool CalculationController::textFieldDidHandleEvent(::TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) {
bool CalculationController::textFieldDidHandleEvent(::TextField * textField, bool returnValue, bool textHasChanged) {
if (returnValue && textHasChanged) {
/* We do not reload the responder because the first responder might be the
* toolbox (or the variable box) and reloading the responder would corrupt

View File

@@ -40,7 +40,7 @@ public:
void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override;
/* TextField delegate */
bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) override;
bool textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textHasChanged) override;
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;

View File

@@ -112,8 +112,7 @@ bool SequenceToolbox::selectAddedCell(int selectedRow){
currentChar += strlen(subscriptLayout->text());
buffer[currentChar++] = ')';
buffer[currentChar] = 0;
sender()->insertTextAtLocation(buffer, sender()->cursorLocation());
sender()->setCursorLocation(sender()->cursorLocation()+currentChar);
sender()->handleEventWithText(buffer);
app()->dismissModalViewController();
return true;
}

View File

@@ -102,9 +102,7 @@ bool TextFieldDelegateApp::textFieldDidReceiveEvent(TextField * textField, Ion::
textField->setEditing(true);
}
const char * xnt = privateXNT(textField);
textField->insertTextAtLocation(xnt, textField->cursorLocation());
textField->setCursorLocation(textField->cursorLocation()+strlen(xnt));
return true;
return textField->handleEventWithText(xnt);
}
return false;
}

View File

@@ -65,11 +65,7 @@ bool VariableBoxController::ContentViewController::handleEvent(Ion::Events::Even
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));
m_textFieldCaller->handleEventWithText(editedText);
#if MATRIX_VARIABLES
m_selectableTableView.deselectTable();
m_currentPage = Page::RootMenu;

View File

@@ -67,6 +67,7 @@ objs += $(addprefix escher/src/,\
text_cursor_view.o\
text_area.o\
text_field.o\
text_input_helpers.o\
text_view.o\
tiled_view.o\
timer.o\

View File

@@ -63,6 +63,7 @@
#include <escher/text_area_delegate.h>
#include <escher/text_field.h>
#include <escher/text_field_delegate.h>
#include <escher/text_input_helpers.h>
#include <escher/text_view.h>
#include <escher/tab_view_controller.h>
#include <escher/tab_view_data_source.h>

View File

@@ -15,14 +15,15 @@ public:
void setDelegate(TextAreaDelegate * delegate) { m_delegate = delegate; }
Toolbox * toolbox() override;
bool handleEvent(Ion::Events::Event event) override;
bool handleEventWithText(const char * text, bool indentation = false);
void setText(char * textBuffer, size_t textBufferSize);
bool insertText(const char * textBuffer) { return m_contentView.insertText(textBuffer); }
bool insertTextWithIndentation(const char * textBuffer);
bool insertTextAtLocation(const char * textBuffer, int location) { return m_contentView.insertTextAtLocation(textBuffer, location); }
bool insertTextWithIndentation(const char * textBuffer, int location);
int indentationBeforeCursor() const;
void removeChar() { m_contentView.removeChar(); }
bool removeChar();
const char * text() const { return m_contentView.text(); }
int cursorLocation() const { return m_contentView.cursorLocation(); }
void moveCursor(int deltaX);
bool setCursorLocation(int location);
private:
class Text {
public:
@@ -97,8 +98,8 @@ private:
const char * text() const;
const Text * getText() const { return &m_text; }
int cursorLocation() const { return m_cursorIndex; }
bool insertText(const char * text);
void moveCursorIndex(int deltaX);
bool insertTextAtLocation(const char * text, int location);
void setCursorLocation(int cursorLocation);
void moveCursorGeo(int deltaX, int deltaY);
void removeChar();
bool removeEndOfLine();

View File

@@ -30,6 +30,7 @@ public:
* the maximum buffer capacity) and false is returned. */
bool insertTextAtLocation(const char * text, int location);
KDSize minimalSizeForOptimalDisplay() const override;
bool handleEventWithText(const char * text);
bool handleEvent(Ion::Events::Event event) override;
bool textFieldShouldFinishEditing(Ion::Events::Event event);
constexpr static int maxBufferSize() {

View File

@@ -9,7 +9,7 @@ public:
virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) = 0;
virtual bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { return false; };
virtual bool textFieldDidAbortEditing(TextField * textField, const char * text) {return false;};
virtual bool textFieldDidHandleEvent(TextField * textField, Ion::Events::Event event, bool returnValue, bool textHasChanged) { return returnValue; };
virtual bool textFieldDidHandleEvent(TextField * textField, bool returnValue, bool textHasChanged) { return returnValue; };
virtual Toolbox * toolboxForTextField(TextField * textField) = 0;
};

View File

@@ -0,0 +1,16 @@
#ifndef ESCHER_TEXT_INPUT_HELPERS_H
#define ESCHER_TEXT_INPUT_HELPERS_H
#include <escher/i18n.h>
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
* - The end of the text */
}
#endif

View File

@@ -1,5 +1,6 @@
#include <escher/text_area.h>
#include <escher/clipboard.h>
#include <escher/text_input_helpers.h>
#include <stddef.h>
#include <assert.h>
@@ -227,18 +228,18 @@ const char * TextArea::TextArea::ContentView::text() const {
return m_text.text();
}
bool TextArea::TextArea::ContentView::insertText(const char * text) {
bool TextArea::TextArea::ContentView::insertTextAtLocation(const char * text, int location) {
int textSize = strlen(text);
if (m_text.textLength() + textSize >= m_text.bufferSize() || textSize == 0) {
return false;
}
bool lineBreak = false;
int currentLocation = location;
while (*text != 0) {
lineBreak |= *text == '\n';
m_text.insertChar(*text++, m_cursorIndex++);
m_text.insertChar(*text++, currentLocation++);
}
layoutSubviews(); // Reposition the cursor
markRectAsDirty(dirtyRectFromCursorPosition(m_cursorIndex-1, lineBreak));
markRectAsDirty(dirtyRectFromCursorPosition(currentLocation-1, lineBreak));
return true;
}
@@ -295,14 +296,10 @@ void TextArea::TextArea::ContentView::moveCursorGeo(int deltaX, int deltaY) {
layoutSubviews();
}
void TextArea::TextArea::ContentView::moveCursorIndex(int deltaX) {
assert(deltaX == -1 || deltaX == 1);
if (deltaX == -1 && m_cursorIndex>0) {
m_cursorIndex--;
}
if (deltaX == 1 && m_text[m_cursorIndex] != 0) {
m_cursorIndex++;
}
void TextArea::TextArea::ContentView::setCursorLocation(int location) {
int adjustedLocation = location < 0 ? 0 : location;
adjustedLocation = adjustedLocation > (signed int)m_text.textLength() ? (signed int)m_text.textLength() : adjustedLocation;
m_cursorIndex = adjustedLocation;
layoutSubviews();
}
@@ -334,35 +331,44 @@ Toolbox * TextArea::toolbox() {
return nullptr;
}
bool TextArea::handleEventWithText(const char * text, bool indentation) {
int nextCursorLocation = cursorLocation();
if ((indentation && insertTextWithIndentation(text, cursorLocation())) || insertTextAtLocation(text, cursorLocation())) {
nextCursorLocation += TextInputHelpers::CursorIndexInCommand(text);
}
setCursorLocation(nextCursorLocation);
return true;
}
bool TextArea::handleEvent(Ion::Events::Event event) {
if (m_delegate != nullptr && m_delegate->textAreaDidReceiveEvent(this, event)) {
} else if (Responder::handleEvent(event)) {
// The only event Responder handles is 'Toolbox' displaying.
return true;
} else if (event == Ion::Events::Left) {
m_contentView.moveCursorIndex(-1);
return setCursorLocation(cursorLocation()-1);
} else if (event == Ion::Events::Right) {
m_contentView.moveCursorIndex(1);
return setCursorLocation(cursorLocation()+1);
} else if (event == Ion::Events::Up) {
m_contentView.moveCursorGeo(0, -1);
} else if (event == Ion::Events::Down) {
m_contentView.moveCursorGeo(0, 1);
} else if (event == Ion::Events::ShiftLeft) {
m_contentView.moveCursorGeo(-INT_MAX/2, 0);
m_contentView.moveCursorGeo(-INT_MAX/2, 0);
} else if (event == Ion::Events::ShiftRight) {
m_contentView.moveCursorGeo(INT_MAX/2, 0);
m_contentView.moveCursorGeo(INT_MAX/2, 0);
} else if (event == Ion::Events::Backspace) {
removeChar();
return removeChar();
} else if (event.hasText()) {
insertText(event.text());
return handleEventWithText(event.text());
} else if (event == Ion::Events::EXE) {
insertText("\n");
return handleEventWithText("\n");
} else if (event == Ion::Events::Clear) {
if (!m_contentView.removeEndOfLine()) {
m_contentView.removeStartOfLine();
}
} else if (event == Ion::Events::Paste) {
insertText(Clipboard::sharedClipboard()->storedText());
return handleEventWithText(Clipboard::sharedClipboard()->storedText());
} else {
return false;
}
@@ -382,9 +388,9 @@ void TextArea::setText(char * textBuffer, size_t textBufferSize) {
m_contentView.moveCursorGeo(0, 0);
}
bool TextArea::insertTextWithIndentation(const char * textBuffer) {
bool TextArea::insertTextWithIndentation(const char * textBuffer, int location) {
int indentation = indentationBeforeCursor();
char spaceString[indentation+1];
char spaceString[indentation+1]; // WOUHOU
for (int i = 0; i < indentation; i++) {
spaceString[i] = ' ';
}
@@ -400,11 +406,13 @@ bool TextArea::insertTextWithIndentation(const char * textBuffer) {
if (m_contentView.getText()->textLength() + textSize + totalIndentationSize >= m_contentView.getText()->bufferSize() || textSize == 0) {
return false;
}
int currentLocation = location;
for (size_t i = 0; i < strlen(textBuffer); i++) {
const char charString[] = {textBuffer[i], 0};
insertText(charString);
insertTextAtLocation(charString, currentLocation++);
if (textBuffer[i] == '\n') {
insertText(spaceString);
insertTextAtLocation(spaceString, currentLocation);
currentLocation += strlen(spaceString);
}
}
return true;
@@ -424,11 +432,14 @@ int TextArea::indentationBeforeCursor() const {
return indentationSize;
}
void TextArea::moveCursor(int deltaX) {
int sign = deltaX > 0? 1 : -1;
int numberSteps = deltaX * sign;
for (int i = 0; i < numberSteps; i++) {
m_contentView.moveCursorIndex(sign);
}
bool TextArea::setCursorLocation(int location) {
m_contentView.setCursorLocation(location);
scrollToContentRect(m_contentView.cursorRect(), true);
return true;
}
bool TextArea::removeChar() {
m_contentView.removeChar();
scrollToContentRect(m_contentView.cursorRect(), true);
return true;
}

View File

@@ -1,4 +1,5 @@
#include <escher/text_field.h>
#include <escher/text_input_helpers.h>
#include <escher/clipboard.h>
#include <assert.h>
@@ -277,10 +278,6 @@ bool TextField::insertTextAtLocation(const char * text, int location) {
}
bool TextField::privateHandleEvent(Ion::Events::Event event) {
assert(m_delegate != nullptr);
if (m_delegate->textFieldDidReceiveEvent(this, event)) {
return true;
}
if (Responder::handleEvent(event)) {
/* The only event Responder handles is 'Toolbox' displaying. In that case,
* the text field is forced into editing mode. */
@@ -342,20 +339,6 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) {
deleteCharPrecedingCursor();
return true;
}
if (event.hasText()) {
if (!isEditing()) {
setEditing(true);
}
int nextCursorLocation = draftTextLength();
if (insertTextAtLocation(event.text(), cursorLocation())) {
/* All events whose text is longer than 2 have parenthesis. In these cases,
* we want to position the cursor before the last parenthesis */
int cursorDelta = strlen(event.text()) > 2 ? -1 : 0;
nextCursorLocation = cursorLocation() + strlen(event.text()) + cursorDelta;
}
setCursorLocation(nextCursorLocation);
return true;
}
if (event == Ion::Events::Back && isEditing()) {
setEditing(false);
reloadScroll();
@@ -377,18 +360,6 @@ bool TextField::privateHandleEvent(Ion::Events::Event event) {
setEditing(true, true);
return true;
}
if (event == Ion::Events::Paste) {
if (!isEditing()) {
setEditing(true);
}
int nextCursorLocation = draftTextLength();
if (insertTextAtLocation(Clipboard::sharedClipboard()->storedText(), cursorLocation())) {
nextCursorLocation = cursorLocation() + strlen(Clipboard::sharedClipboard()->storedText());
}
setCursorLocation(nextCursorLocation);
return true;
}
return false;
}
@@ -415,9 +386,18 @@ bool TextField::textFieldShouldFinishEditing(Ion::Events::Event event) {
bool TextField::handleEvent(Ion::Events::Event event) {
assert(m_delegate != nullptr);
if (m_delegate->textFieldDidReceiveEvent(this, event)) {
return true;
}
if (event.hasText()) {
return handleEventWithText(event.text());
}
if (event == Ion::Events::Paste) {
return handleEventWithText(Clipboard::sharedClipboard()->storedText());
}
size_t previousTextLength = strlen(text());
bool didHandleEvent = privateHandleEvent(event);
return m_delegate->textFieldDidHandleEvent(this, event, didHandleEvent, strlen(text()) != previousTextLength);
return m_delegate->textFieldDidHandleEvent(this, didHandleEvent, strlen(text()) != previousTextLength);
}
void TextField::scrollToCursor() {
@@ -426,3 +406,19 @@ void TextField::scrollToCursor() {
}
scrollToContentRect(m_contentView.cursorRect(), true);
}
bool TextField::handleEventWithText(const char * eventText) {
size_t previousTextLength = strlen(text());
if (!isEditing()) {
setEditing(true);
}
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);
}
setCursorLocation(nextCursorLocation);
return m_delegate->textFieldDidHandleEvent(this, true, strlen(text()) != previousTextLength);
}

View File

@@ -0,0 +1,17 @@
#include <escher/text_input_helpers.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] == '\'') {
return i + 1;
}
}
}
return strlen(text);
}
}