mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[escher] XNT button is now cyclic
This commit is contained in:
@@ -60,6 +60,7 @@ apps_src += $(addprefix apps/,\
|
|||||||
suspend_timer.cpp \
|
suspend_timer.cpp \
|
||||||
timer_manager.cpp \
|
timer_manager.cpp \
|
||||||
title_bar_view.cpp \
|
title_bar_view.cpp \
|
||||||
|
xnt_loop.cpp \
|
||||||
)
|
)
|
||||||
|
|
||||||
tests_src += $(addprefix apps/,\
|
tests_src += $(addprefix apps/,\
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "shared/global_context.h"
|
#include "shared/global_context.h"
|
||||||
#include "clock_timer.h"
|
#include "clock_timer.h"
|
||||||
#include "on_boarding/prompt_controller.h"
|
#include "on_boarding/prompt_controller.h"
|
||||||
|
#include "xnt_loop.h"
|
||||||
|
|
||||||
#include <ion/events.h>
|
#include <ion/events.h>
|
||||||
|
|
||||||
@@ -48,6 +49,8 @@ public:
|
|||||||
void displayExamModePopUp(GlobalPreferences::ExamMode mode);
|
void displayExamModePopUp(GlobalPreferences::ExamMode mode);
|
||||||
void shutdownDueToLowBattery();
|
void shutdownDueToLowBattery();
|
||||||
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
|
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
|
||||||
|
CodePoint XNT(CodePoint defaultXNT, bool * shouldRemoveLastCharacter) { m_XNTLoop.XNT(defaultXNT, shouldRemoveLastCharacter); }
|
||||||
|
void resetXNT() { m_XNTLoop.reset(); }
|
||||||
OnBoarding::PromptController * promptController();
|
OnBoarding::PromptController * promptController();
|
||||||
void redrawWindow(bool force = false);
|
void redrawWindow(bool force = false);
|
||||||
void activateExamMode(GlobalPreferences::ExamMode examMode);
|
void activateExamMode(GlobalPreferences::ExamMode examMode);
|
||||||
@@ -85,6 +88,7 @@ private:
|
|||||||
OnBoarding::App::Snapshot m_onBoardingSnapshot;
|
OnBoarding::App::Snapshot m_onBoardingSnapshot;
|
||||||
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
|
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
|
||||||
USB::App::Snapshot m_usbConnectedSnapshot;
|
USB::App::Snapshot m_usbConnectedSnapshot;
|
||||||
|
XNTLoop m_XNTLoop;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -129,9 +129,10 @@ VariableBoxController * App::variableBoxForInputEventHandler(InputEventHandler *
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event) {
|
bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event) {
|
||||||
const char * pythonText = Helpers::PythonTextForEvent(event);
|
bool shouldRemoveLastCharacter = false;
|
||||||
if (pythonText != nullptr) {
|
char buffer[CodePoint::MaxCodePointCharLength + 1];
|
||||||
textInput->handleEventWithText(pythonText);
|
if (Helpers::PythonTextForEvent(event, buffer, &shouldRemoveLastCharacter)) {
|
||||||
|
textInput->handleEventWithText(buffer, false, false, shouldRemoveLastCharacter);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <escher/metric.h>
|
#include <escher/metric.h>
|
||||||
#include <ion.h>
|
#include <ion.h>
|
||||||
#include "../global_preferences.h"
|
#include "../global_preferences.h"
|
||||||
|
#include <apps/apps_container.h>
|
||||||
|
|
||||||
using namespace Shared;
|
using namespace Shared;
|
||||||
|
|
||||||
@@ -72,6 +73,10 @@ void EditorController::viewDidDisappear() {
|
|||||||
m_menuController->scriptContentEditionDidFinish();
|
m_menuController->scriptContentEditionDidFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EditorController::textAreaDidReceiveNoneXNTEvent() {
|
||||||
|
AppsContainer::sharedAppsContainer()->resetXNT();
|
||||||
|
}
|
||||||
|
|
||||||
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
|
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
|
||||||
if (App::app()->textInputDidReceiveEvent(textArea, event)) {
|
if (App::app()->textInputDidReceiveEvent(textArea, event)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -81,7 +86,6 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (event == Ion::Events::Backspace && textArea->selectionIsEmpty()) {
|
if (event == Ion::Events::Backspace && textArea->selectionIsEmpty()) {
|
||||||
/* If the cursor is on the left of the text of a line, backspace one
|
/* If the cursor is on the left of the text of a line, backspace one
|
||||||
* indentation space at a time. */
|
* indentation space at a time. */
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public:
|
|||||||
TELEMETRY_ID("Editor");
|
TELEMETRY_ID("Editor");
|
||||||
|
|
||||||
/* TextAreaDelegate */
|
/* TextAreaDelegate */
|
||||||
|
void textAreaDidReceiveNoneXNTEvent() override;
|
||||||
bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override;
|
bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override;
|
||||||
|
|
||||||
/* InputEventHandlerDelegate */
|
/* InputEventHandlerDelegate */
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include <escher/clipboard.h>
|
#include <escher/clipboard.h>
|
||||||
|
#include <apps/apps_container.h>
|
||||||
|
|
||||||
namespace Code {
|
namespace Code {
|
||||||
namespace Helpers {
|
namespace Helpers {
|
||||||
|
|
||||||
const char * PythonTextForEvent(Ion::Events::Event event) {
|
bool PythonTextForEvent(Ion::Events::Event event, char * buffer, bool * shouldRemoveLastCharacter) {
|
||||||
for (size_t i=0; i<NumberOfPythonTextPairs; i++) {
|
for (size_t i=0; i<NumberOfPythonTextPairs; i++) {
|
||||||
UTF8Helper::TextPair pair = PythonTextPairs[i];
|
UTF8Helper::TextPair pair = PythonTextPairs[i];
|
||||||
if (event.text() == pair.firstString()) {
|
if (event.text() == pair.firstString()) {
|
||||||
return pair.secondString();
|
strcpy(buffer, pair.secondString());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (event == Ion::Events::XNT) {
|
if (event == Ion::Events::XNT) {
|
||||||
return "x";
|
CodePoint XNT = AppsContainer::sharedAppsContainer()->XNT('x', shouldRemoveLastCharacter);
|
||||||
|
buffer[UTF8Decoder::CodePointToChars(XNT, buffer, CodePoint::MaxCodePointCharLength + 1)] = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
namespace Code {
|
namespace Code {
|
||||||
namespace Helpers {
|
namespace Helpers {
|
||||||
|
|
||||||
const char * PythonTextForEvent(Ion::Events::Event event);
|
bool PythonTextForEvent(Ion::Events::Event event, char * buffer, bool * shouldRemoveLastCharacter);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -426,14 +426,14 @@ bool PythonTextArea::handleEvent(Ion::Events::Event event) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
|
bool PythonTextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText, bool shouldRemoveLastCharacter) {
|
||||||
if (*text == 0) {
|
if (*text == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (m_contentView.isAutocompleting()) {
|
if (m_contentView.isAutocompleting()) {
|
||||||
removeAutocompletion();
|
removeAutocompletion();
|
||||||
}
|
}
|
||||||
bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText);
|
bool result = TextArea::handleEventWithText(text, indentation, forceCursorRightOfText, shouldRemoveLastCharacter);
|
||||||
addAutocompletion();
|
addAutocompletion();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -493,9 +493,10 @@ bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIn
|
|||||||
|
|
||||||
if (textToInsertLength > 0) {
|
if (textToInsertLength > 0) {
|
||||||
// Try to insert the text (this might fail if the buffer is full)
|
// Try to insert the text (this might fail if the buffer is full)
|
||||||
if (!m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength)) {
|
if (!m_contentView.isAbleToInsertTextAt(textToInsertLength, autocompletionLocation, false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
m_contentView.insertTextAtLocation(textToInsert, const_cast<char *>(autocompletionLocation), textToInsertLength);
|
||||||
autocompletionLocation += textToInsertLength;
|
autocompletionLocation += textToInsertLength;
|
||||||
m_contentView.setAutocompleting(true);
|
m_contentView.setAutocompleting(true);
|
||||||
m_contentView.setAutocompletionEnd(autocompletionLocation);
|
m_contentView.setAutocompletionEnd(autocompletionLocation);
|
||||||
@@ -507,7 +508,8 @@ bool PythonTextArea::addAutocompletionTextAtIndex(int nextIndex, int * currentIn
|
|||||||
assert(strlen(parentheses) == parenthesesLength);
|
assert(strlen(parentheses) == parenthesesLength);
|
||||||
/* If couldInsertText is false, we should not try to add the parentheses as
|
/* If couldInsertText is false, we should not try to add the parentheses as
|
||||||
* there was already not enough space to add the autocompletion. */
|
* there was already not enough space to add the autocompletion. */
|
||||||
if (addParentheses && m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength)) {
|
if (addParentheses && m_contentView.isAbleToInsertTextAt(parenthesesLength, autocompletionLocation, false)) {
|
||||||
|
m_contentView.insertTextAtLocation(parentheses, const_cast<char *>(autocompletionLocation), parenthesesLength);
|
||||||
m_contentView.setAutocompleting(true);
|
m_contentView.setAutocompleting(true);
|
||||||
m_contentView.setAutocompletionEnd(autocompletionLocation + parenthesesLength);
|
m_contentView.setAutocompletionEnd(autocompletionLocation + parenthesesLength);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public:
|
|||||||
void loadSyntaxHighlighter() { m_contentView.loadSyntaxHighlighter(); }
|
void loadSyntaxHighlighter() { m_contentView.loadSyntaxHighlighter(); }
|
||||||
void unloadSyntaxHighlighter() { m_contentView.unloadSyntaxHighlighter(); }
|
void unloadSyntaxHighlighter() { m_contentView.unloadSyntaxHighlighter(); }
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
|
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) override;
|
||||||
/* autocompletionType returns:
|
/* autocompletionType returns:
|
||||||
* - EndOfIdentifier if there is currently autocompletion, or if the cursor is
|
* - EndOfIdentifier if there is currently autocompletion, or if the cursor is
|
||||||
* at the end of an identifier,
|
* at the end of an identifier,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace Shared {
|
|||||||
class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public LayoutFieldDelegate {
|
class ExpressionFieldDelegateApp : public TextFieldDelegateApp, public LayoutFieldDelegate {
|
||||||
public:
|
public:
|
||||||
virtual ~ExpressionFieldDelegateApp() = default;
|
virtual ~ExpressionFieldDelegateApp() = default;
|
||||||
|
void layoutFieldDidReceiveNoneXNTEvent() override { AppsContainer::sharedAppsContainer()->resetXNT(); }
|
||||||
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
|
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
|
||||||
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
|
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
#define SHARED_LAYOUT_FIELD_DELEGATE_H
|
#define SHARED_LAYOUT_FIELD_DELEGATE_H
|
||||||
|
|
||||||
#include "expression_field_delegate_app.h"
|
#include "expression_field_delegate_app.h"
|
||||||
|
#include "../apps_container.h"
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
class LayoutFieldDelegate : public ::LayoutFieldDelegate {
|
class LayoutFieldDelegate : public ::LayoutFieldDelegate {
|
||||||
public:
|
public:
|
||||||
|
void layoutFieldDidReceiveNoneXNTEvent() override { AppsContainer::sharedAppsContainer()->resetXNT(); }
|
||||||
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
|
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
|
||||||
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
|
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
|
||||||
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) override;
|
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) override;
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
#define SHARED_TEXT_FIELD_DELEGATE_H
|
#define SHARED_TEXT_FIELD_DELEGATE_H
|
||||||
|
|
||||||
#include "text_field_delegate_app.h"
|
#include "text_field_delegate_app.h"
|
||||||
|
#include "../apps_container.h"
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
class TextFieldDelegate : public ::TextFieldDelegate {
|
class TextFieldDelegate : public ::TextFieldDelegate {
|
||||||
public:
|
public:
|
||||||
|
void textFieldDidReceiveNoneXNTEvent() override { AppsContainer::sharedAppsContainer()->resetXNT(); }
|
||||||
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
||||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -72,10 +72,12 @@ bool TextFieldDelegateApp::fieldDidReceiveEvent(EditableField * field, Responder
|
|||||||
if (XNTCanBeOverriden()) {
|
if (XNTCanBeOverriden()) {
|
||||||
xnt = field->XNTCodePoint(xnt);
|
xnt = field->XNTCodePoint(xnt);
|
||||||
}
|
}
|
||||||
|
bool shouldRemoveLastCharacter = false;
|
||||||
|
xnt = AppsContainer::sharedAppsContainer()->XNT(xnt, &shouldRemoveLastCharacter);
|
||||||
size_t length = UTF8Decoder::CodePointToChars(xnt, buffer, bufferSize);
|
size_t length = UTF8Decoder::CodePointToChars(xnt, buffer, bufferSize);
|
||||||
assert(length < bufferSize - 1);
|
assert(length < bufferSize - 1);
|
||||||
buffer[length] = 0;
|
buffer[length] = 0;
|
||||||
return field->handleEventWithText(buffer);
|
return field->handleEventWithText(buffer, false, false, shouldRemoveLastCharacter);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "input_event_handler_delegate_app.h"
|
#include "input_event_handler_delegate_app.h"
|
||||||
#include <escher/text_field_delegate.h>
|
#include <escher/text_field_delegate.h>
|
||||||
#include <apps/i18n.h>
|
#include <apps/i18n.h>
|
||||||
|
#include "../apps_container.h"
|
||||||
|
|
||||||
class EditableField;
|
class EditableField;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ public:
|
|||||||
Poincare::Context * localContext() override;
|
Poincare::Context * localContext() override;
|
||||||
virtual bool XNTCanBeOverriden() const { return true; }
|
virtual bool XNTCanBeOverriden() const { return true; }
|
||||||
virtual CodePoint XNT() { return 'x'; }
|
virtual CodePoint XNT() { return 'x'; }
|
||||||
|
virtual void textFieldDidReceiveNoneXNTEvent() override { AppsContainer::sharedAppsContainer()->resetXNT(); }
|
||||||
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
||||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||||
bool isAcceptableText(const char * text);
|
bool isAcceptableText(const char * text);
|
||||||
|
|||||||
22
apps/xnt_loop.cpp
Normal file
22
apps/xnt_loop.cpp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#include "xnt_loop.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
CodePoint XNTLoop::XNT(CodePoint defaultCodePoint, bool * shouldRemoveLastCharacter) {
|
||||||
|
assert(shouldRemoveLastCharacter != nullptr);
|
||||||
|
static constexpr CodePoint XNTCodePoints[] = {'x', 'n', 't', UCodePointGreekSmallLetterTheta};
|
||||||
|
int XNTCodePointSize = sizeof(XNTCodePoints) / sizeof(CodePoint);
|
||||||
|
|
||||||
|
if (m_loopIndex == -1) {
|
||||||
|
for (int i = 0; i < XNTCodePointSize; i++) {
|
||||||
|
if (XNTCodePoints[i] == defaultCodePoint) {
|
||||||
|
m_loopIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*shouldRemoveLastCharacter = true;
|
||||||
|
m_loopIndex = (m_loopIndex + 1) % XNTCodePointSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return XNTCodePoints[m_loopIndex];
|
||||||
|
}
|
||||||
15
apps/xnt_loop.h
Normal file
15
apps/xnt_loop.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef APPS_XNT_LOOP
|
||||||
|
#define APPS_XNT_LOOP
|
||||||
|
|
||||||
|
#include <ion/unicode/code_point.h>
|
||||||
|
|
||||||
|
class XNTLoop {
|
||||||
|
public:
|
||||||
|
XNTLoop(): m_loopIndex(-1) {}
|
||||||
|
void reset() { m_loopIndex = -1; }
|
||||||
|
CodePoint XNT(CodePoint defaultCodePoint, bool * shouldRemoveLastCharacter);
|
||||||
|
private:
|
||||||
|
int m_loopIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -10,7 +10,7 @@ class InputEventHandlerDelegate;
|
|||||||
class InputEventHandler {
|
class InputEventHandler {
|
||||||
public:
|
public:
|
||||||
InputEventHandler(InputEventHandlerDelegate * inputEventHandlerdelegate) : m_inputEventHandlerDelegate(inputEventHandlerdelegate) {}
|
InputEventHandler(InputEventHandlerDelegate * inputEventHandlerdelegate) : m_inputEventHandlerDelegate(inputEventHandlerdelegate) {}
|
||||||
virtual bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) { return false; }
|
virtual bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) { return false; }
|
||||||
protected:
|
protected:
|
||||||
bool handleBoxEvent(Ion::Events::Event event);
|
bool handleBoxEvent(Ion::Events::Event event);
|
||||||
InputEventHandlerDelegate * m_inputEventHandlerDelegate;
|
InputEventHandlerDelegate * m_inputEventHandlerDelegate;
|
||||||
|
|||||||
@@ -27,12 +27,14 @@ public:
|
|||||||
void abortEditionAndDismiss();
|
void abortEditionAndDismiss();
|
||||||
|
|
||||||
/* TextFieldDelegate */
|
/* TextFieldDelegate */
|
||||||
|
void textFieldDidReceiveNoneXNTEvent() override;
|
||||||
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) override;
|
||||||
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) override;
|
||||||
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
|
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
|
||||||
bool textFieldDidAbortEditing(TextField * textField) override;
|
bool textFieldDidAbortEditing(TextField * textField) override;
|
||||||
|
|
||||||
/* LayoutFieldDelegate */
|
/* LayoutFieldDelegate */
|
||||||
|
void layoutFieldDidReceiveNoneXNTEvent() override;
|
||||||
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
|
bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) override;
|
||||||
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
|
bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) override;
|
||||||
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) override;
|
bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) override;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Responder */
|
/* Responder */
|
||||||
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
|
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) override;
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
// TODO: factorize with TextField (see TODO of EditableField)
|
// TODO: factorize with TextField (see TODO of EditableField)
|
||||||
bool shouldFinishEditing(Ion::Events::Event event) override;
|
bool shouldFinishEditing(Ion::Events::Event event) override;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class LayoutField;
|
|||||||
|
|
||||||
class LayoutFieldDelegate : public ContextProvider{
|
class LayoutFieldDelegate : public ContextProvider{
|
||||||
public:
|
public:
|
||||||
|
virtual void layoutFieldDidReceiveNoneXNTEvent() {};
|
||||||
virtual bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) = 0;
|
virtual bool layoutFieldShouldFinishEditing(LayoutField * layoutField, Ion::Events::Event event) = 0;
|
||||||
virtual bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) = 0;
|
virtual bool layoutFieldDidReceiveEvent(LayoutField * layoutField, Ion::Events::Event event) = 0;
|
||||||
virtual bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) { return false; }
|
virtual bool layoutFieldDidFinishEditing(LayoutField * layoutField, Poincare::Layout layoutR, Ion::Events::Event event) { return false; }
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
TextArea(Responder * parentResponder, View * contentView, const KDFont * font = KDFont::LargeFont);
|
TextArea(Responder * parentResponder, View * contentView, const KDFont * font = KDFont::LargeFont);
|
||||||
void setDelegates(InputEventHandlerDelegate * inputEventHandlerDelegate, TextAreaDelegate * delegate) { m_inputEventHandlerDelegate = inputEventHandlerDelegate; m_delegate = delegate; }
|
void setDelegates(InputEventHandlerDelegate * inputEventHandlerDelegate, TextAreaDelegate * delegate) { m_inputEventHandlerDelegate = inputEventHandlerDelegate; m_delegate = delegate; }
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
|
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) override;
|
||||||
void setText(char * textBuffer, size_t textBufferSize);
|
void setText(char * textBuffer, size_t textBufferSize);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -120,7 +120,8 @@ protected:
|
|||||||
const char * editedText() const override { return m_text.text(); }
|
const char * editedText() const override { return m_text.text(); }
|
||||||
size_t editedTextLength() const override { return m_text.textLength(); }
|
size_t editedTextLength() const override { return m_text.textLength(); }
|
||||||
const Text * getText() const { return &m_text; }
|
const Text * getText() const { return &m_text; }
|
||||||
bool insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
|
bool isAbleToInsertTextAt(int textLength, const char * location, bool shouldRemoveLastCharacter) const override;
|
||||||
|
void insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
|
||||||
void moveCursorGeo(int deltaX, int deltaY);
|
void moveCursorGeo(int deltaX, int deltaY);
|
||||||
bool removePreviousGlyph() override;
|
bool removePreviousGlyph() override;
|
||||||
bool removeEndOfLine() override;
|
bool removeEndOfLine() override;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class TextArea;
|
|||||||
|
|
||||||
class TextAreaDelegate {
|
class TextAreaDelegate {
|
||||||
public:
|
public:
|
||||||
|
virtual void textAreaDidReceiveNoneXNTEvent() {};
|
||||||
virtual bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) = 0;
|
virtual bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
void setText(const char * text);
|
void setText(const char * text);
|
||||||
void setEditing(bool isEditing) override { m_contentView.setEditing(isEditing); }
|
void setEditing(bool isEditing) override { m_contentView.setEditing(isEditing); }
|
||||||
CodePoint XNTCodePoint(CodePoint defaultXNTCodePoint) override;
|
CodePoint XNTCodePoint(CodePoint defaultXNTCodePoint) override;
|
||||||
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override;
|
bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false, bool shouldRemoveLastCharacter = false) override;
|
||||||
bool handleEvent(Ion::Events::Event event) override;
|
bool handleEvent(Ion::Events::Event event) override;
|
||||||
constexpr static int maxBufferSize() {
|
constexpr static int maxBufferSize() {
|
||||||
return ContentView::k_maxBufferSize;
|
return ContentView::k_maxBufferSize;
|
||||||
@@ -71,10 +71,11 @@ protected:
|
|||||||
void reinitDraftTextBuffer();
|
void reinitDraftTextBuffer();
|
||||||
void setDraftTextBufferSize(size_t size) { assert(size <= k_maxBufferSize); m_draftTextBufferSize = size; }
|
void setDraftTextBufferSize(size_t size) { assert(size <= k_maxBufferSize); m_draftTextBufferSize = size; }
|
||||||
size_t draftTextBufferSize() const { return m_draftTextBufferSize; }
|
size_t draftTextBufferSize() const { return m_draftTextBufferSize; }
|
||||||
|
bool isAbleToInsertTextAt(int textLength, const char * location, bool shouldRemoveLastCharacter) const override;
|
||||||
/* If the text to be appended is too long to be added without overflowing the
|
/* If the text to be appended is too long to be added without overflowing the
|
||||||
* buffer, nothing is done (not even adding few letters from the text to reach
|
* buffer, nothing is done (not even adding few letters from the text to reach
|
||||||
* the maximum buffer capacity) and false is returned. */
|
* the maximum buffer capacity) and false is returned. */
|
||||||
bool insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
|
void insertTextAtLocation(const char * text, char * location, int textLength = -1) override;
|
||||||
KDSize minimalSizeForOptimalDisplay() const override;
|
KDSize minimalSizeForOptimalDisplay() const override;
|
||||||
bool removePreviousGlyph() override;
|
bool removePreviousGlyph() override;
|
||||||
bool removeEndOfLine() override;
|
bool removeEndOfLine() override;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class TextField;
|
|||||||
|
|
||||||
class TextFieldDelegate {
|
class TextFieldDelegate {
|
||||||
public:
|
public:
|
||||||
|
virtual void textFieldDidReceiveNoneXNTEvent() {};
|
||||||
virtual bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) = 0;
|
virtual bool textFieldShouldFinishEditing(TextField * textField, Ion::Events::Event event) = 0;
|
||||||
virtual bool textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) = 0;
|
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 textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) { return false; }
|
||||||
|
|||||||
@@ -49,7 +49,8 @@ protected:
|
|||||||
|
|
||||||
// Virtual text get/add/remove
|
// Virtual text get/add/remove
|
||||||
virtual const char * text() const = 0;
|
virtual const char * text() const = 0;
|
||||||
virtual bool insertTextAtLocation(const char * text, char * location, int textLength = -1) = 0;
|
virtual bool isAbleToInsertTextAt(int textLength, const char * location, bool shouldRemoveLastCharacter) const = 0;
|
||||||
|
virtual void insertTextAtLocation(const char * text, char * location, int textLength) = 0;
|
||||||
virtual bool removePreviousGlyph() = 0;
|
virtual bool removePreviousGlyph() = 0;
|
||||||
virtual bool removeEndOfLine() = 0;
|
virtual bool removeEndOfLine() = 0;
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ protected:
|
|||||||
/* If the text to be appended is too long to be added without overflowing the
|
/* If the text to be appended is too long to be added without overflowing the
|
||||||
* buffer, nothing is done (not even adding few letters from the text to reach
|
* buffer, nothing is done (not even adding few letters from the text to reach
|
||||||
* the maximum buffer capacity) and false is returned. */
|
* the maximum buffer capacity) and false is returned. */
|
||||||
bool insertTextAtLocation(const char * textBuffer, char * location);
|
void insertTextAtLocation(const char * textBuffer, char * location, int textLength);
|
||||||
bool removeEndOfLine();
|
bool removeEndOfLine();
|
||||||
ContentView * contentView() {
|
ContentView * contentView() {
|
||||||
return const_cast<ContentView *>(nonEditableContentView());
|
return const_cast<ContentView *>(nonEditableContentView());
|
||||||
|
|||||||
@@ -58,6 +58,14 @@ bool InputViewController::textFieldDidAbortEditing(TextField * textField) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputViewController::textFieldDidReceiveNoneXNTEvent() {
|
||||||
|
m_textFieldDelegate->textFieldDidReceiveNoneXNTEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputViewController::layoutFieldDidReceiveNoneXNTEvent() {
|
||||||
|
m_layoutFieldDelegate->layoutFieldDidReceiveNoneXNTEvent();
|
||||||
|
}
|
||||||
|
|
||||||
bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
bool InputViewController::textFieldDidReceiveEvent(TextField * textField, Ion::Events::Event event) {
|
||||||
return m_textFieldDelegate->textFieldDidReceiveEvent(textField, event);
|
return m_textFieldDelegate->textFieldDidReceiveEvent(textField, event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ void LayoutField::reload(KDSize previousSize) {
|
|||||||
markRectAsDirty(bounds());
|
markRectAsDirty(bounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutField::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
|
bool LayoutField::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText, bool shouldRemoveLastCharacter) {
|
||||||
/* The text here can be:
|
/* The text here can be:
|
||||||
* - the result of a key pressed, such as "," or "cos(•)"
|
* - the result of a key pressed, such as "," or "cos(•)"
|
||||||
* - the text added after a toolbox selection
|
* - the text added after a toolbox selection
|
||||||
@@ -417,6 +417,9 @@ bool LayoutField::handleEventWithText(const char * text, bool indentation, bool
|
|||||||
if (currentNumberOfLayouts + resultLayout.numberOfDescendants(true) >= k_maxNumberOfLayouts) {
|
if (currentNumberOfLayouts + resultLayout.numberOfDescendants(true) >= k_maxNumberOfLayouts) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (shouldRemoveLastCharacter) {
|
||||||
|
cursor->performBackspace();
|
||||||
|
}
|
||||||
insertLayoutAtCursor(resultLayout, resultExpression, forceCursorRightOfText);
|
insertLayoutAtCursor(resultLayout, resultExpression, forceCursorRightOfText);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -431,6 +434,9 @@ bool LayoutField::shouldFinishEditing(Ion::Events::Event event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutField::handleEvent(Ion::Events::Event event) {
|
bool LayoutField::handleEvent(Ion::Events::Event event) {
|
||||||
|
if (m_delegate && event != Ion::Events::XNT) {
|
||||||
|
m_delegate->layoutFieldDidReceiveNoneXNTEvent();
|
||||||
|
}
|
||||||
bool didHandleEvent = false;
|
bool didHandleEvent = false;
|
||||||
KDSize previousSize = minimalSizeForOptimalDisplay();
|
KDSize previousSize = minimalSizeForOptimalDisplay();
|
||||||
bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded();
|
bool shouldRecomputeLayout = m_contentView.cursor()->showEmptyLayoutIfNeeded();
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ static inline void InsertSpacesAtLocation(int spacesCount, char * buffer, int bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) {
|
bool TextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText, bool shouldRemoveLastCharacter) {
|
||||||
if (*text == 0) {
|
if (*text == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -123,11 +123,19 @@ bool TextArea::handleEventWithText(const char * text, bool indentation, bool for
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the text
|
int textLength = strlen(text);
|
||||||
if (!insertTextAtLocation(text, insertionPosition)) {
|
if (!contentView()->isAbleToInsertTextAt(textLength, insertionPosition, shouldRemoveLastCharacter)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldRemoveLastCharacter) {
|
||||||
|
removePreviousGlyph();
|
||||||
|
insertionPosition = const_cast<char *>(cursorLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the text
|
||||||
|
insertTextAtLocation(text, insertionPosition, textLength);
|
||||||
|
|
||||||
// Insert the indentation
|
// Insert the indentation
|
||||||
if (indentation) {
|
if (indentation) {
|
||||||
UTF8Helper::PerformAtCodePoints(
|
UTF8Helper::PerformAtCodePoints(
|
||||||
@@ -160,6 +168,9 @@ bool TextArea::handleEventWithText(const char * text, bool indentation, bool for
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TextArea::handleEvent(Ion::Events::Event event) {
|
bool TextArea::handleEvent(Ion::Events::Event event) {
|
||||||
|
if (m_delegate != nullptr && event != Ion::Events::XNT) {
|
||||||
|
m_delegate->textAreaDidReceiveNoneXNTEvent();
|
||||||
|
}
|
||||||
if (m_delegate != nullptr && m_delegate->textAreaDidReceiveEvent(this, event)) {
|
if (m_delegate != nullptr && m_delegate->textAreaDidReceiveEvent(this, event)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -575,12 +586,21 @@ void TextArea::ContentView::setText(char * textBuffer, size_t textBufferSize) {
|
|||||||
m_cursorLocation = text();
|
m_cursorLocation = text();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextArea::ContentView::insertTextAtLocation(const char * text, char * location, int textLength) {
|
bool TextArea::ContentView::isAbleToInsertTextAt(int textLength, const char * location, bool shouldRemoveLastCharacter) const {
|
||||||
|
int removedCharacters = 0;
|
||||||
|
if (shouldRemoveLastCharacter) {
|
||||||
|
UTF8Decoder decoder(m_text.text(), location);
|
||||||
|
const char * previousGlyphPos = decoder.previousGlyphPosition();
|
||||||
|
assert(previousGlyphPos != nullptr);
|
||||||
|
removedCharacters = location - previousGlyphPos;
|
||||||
|
}
|
||||||
|
return m_text.textLength() + textLength - removedCharacters < m_text.bufferSize() && textLength != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextArea::ContentView::insertTextAtLocation(const char * text, char * location, int textLength) {
|
||||||
int textLen = textLength < 0 ? strlen(text) : textLength;
|
int textLen = textLength < 0 ? strlen(text) : textLength;
|
||||||
assert(textLen < 0 || textLen <= strlen(text));
|
assert(textLen < 0 || textLen <= strlen(text));
|
||||||
if (m_text.textLength() + textLen >= m_text.bufferSize() || textLen == 0) {
|
assert(isAbleToInsertTextAt(textLen, location, false));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan for \n
|
// Scan for \n
|
||||||
bool lineBreak = UTF8Helper::HasCodePoint(text, '\n', text + textLen);
|
bool lineBreak = UTF8Helper::HasCodePoint(text, '\n', text + textLen);
|
||||||
@@ -589,7 +609,6 @@ bool TextArea::ContentView::insertTextAtLocation(const char * text, char * locat
|
|||||||
// Replace System parentheses (used to keep layout tree structure) by normal parentheses
|
// Replace System parentheses (used to keep layout tree structure) by normal parentheses
|
||||||
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(location, textLen);
|
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(location, textLen);
|
||||||
reloadRectFromPosition(location, lineBreak);
|
reloadRectFromPosition(location, lineBreak);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextArea::ContentView::removePreviousGlyph() {
|
bool TextArea::ContentView::removePreviousGlyph() {
|
||||||
|
|||||||
@@ -119,14 +119,23 @@ void TextField::ContentView::reinitDraftTextBuffer() {
|
|||||||
setCursorLocation(s_draftTextBuffer);
|
setCursorLocation(s_draftTextBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextField::ContentView::insertTextAtLocation(const char * text, char * location, int textLen) {
|
bool TextField::ContentView::isAbleToInsertTextAt(int textLength, const char * location, bool shouldRemoveLastCharacter) const {
|
||||||
|
int removedCharacters = 0;
|
||||||
|
if (shouldRemoveLastCharacter) {
|
||||||
|
UTF8Decoder decoder(s_draftTextBuffer, location);
|
||||||
|
const char * previousGlyphPos = decoder.previousGlyphPosition();
|
||||||
|
assert(previousGlyphPos != nullptr);
|
||||||
|
removedCharacters = location - previousGlyphPos;
|
||||||
|
}
|
||||||
|
return m_currentDraftTextLength + textLength - removedCharacters < m_draftTextBufferSize && textLength != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextField::ContentView::insertTextAtLocation(const char * text, char * location, int textLen) {
|
||||||
assert(m_isEditing);
|
assert(m_isEditing);
|
||||||
|
|
||||||
size_t textLength = textLen < 0 ? strlen(text) : (size_t)textLen;
|
size_t textLength = textLen < 0 ? strlen(text) : (size_t)textLen;
|
||||||
// TODO when paste fails because of a too big message, create a pop-up
|
// TODO when paste fails because of a too big message, create a pop-up
|
||||||
if (m_currentDraftTextLength + textLength >= m_draftTextBufferSize || textLength == 0) {
|
assert(isAbleToInsertTextAt(textLength, location, false));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memmove(location + textLength, location, (s_draftTextBuffer + m_currentDraftTextLength + 1) - location);
|
memmove(location + textLength, location, (s_draftTextBuffer + m_currentDraftTextLength + 1) - location);
|
||||||
|
|
||||||
@@ -139,7 +148,6 @@ bool TextField::ContentView::insertTextAtLocation(const char * text, char * loca
|
|||||||
m_currentDraftTextLength += copySize-1; // Do no count the null-termination
|
m_currentDraftTextLength += copySize-1; // Do no count the null-termination
|
||||||
|
|
||||||
reloadRectFromPosition(m_horizontalAlignment == 0.0f ? location : s_draftTextBuffer);
|
reloadRectFromPosition(m_horizontalAlignment == 0.0f ? location : s_draftTextBuffer);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KDSize TextField::ContentView::minimalSizeForOptimalDisplay() const {
|
KDSize TextField::ContentView::minimalSizeForOptimalDisplay() const {
|
||||||
@@ -416,6 +424,9 @@ CodePoint TextField::XNTCodePoint(CodePoint defaultXNTCodePoint) {
|
|||||||
|
|
||||||
bool TextField::handleEvent(Ion::Events::Event event) {
|
bool TextField::handleEvent(Ion::Events::Event event) {
|
||||||
assert(m_delegate != nullptr);
|
assert(m_delegate != nullptr);
|
||||||
|
if (event != Ion::Events::XNT) {
|
||||||
|
m_delegate->textFieldDidReceiveNoneXNTEvent();
|
||||||
|
}
|
||||||
size_t previousTextLength = strlen(text());
|
size_t previousTextLength = strlen(text());
|
||||||
bool didHandleEvent = false;
|
bool didHandleEvent = false;
|
||||||
if (privateHandleMoveEvent(event)) {
|
if (privateHandleMoveEvent(event)) {
|
||||||
@@ -486,7 +497,7 @@ bool TextField::privateHandleSelectEvent(Ion::Events::Event event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextField::handleEventWithText(const char * eventText, bool indentation, bool forceCursorRightOfText) {
|
bool TextField::handleEventWithText(const char * eventText, bool indentation, bool forceCursorRightOfText, bool shouldRemoveLastCharacter) {
|
||||||
size_t previousTextLength = strlen(text());
|
size_t previousTextLength = strlen(text());
|
||||||
|
|
||||||
if (!isEditing()) {
|
if (!isEditing()) {
|
||||||
@@ -518,7 +529,13 @@ bool TextField::handleEventWithText(const char * eventText, bool indentation, bo
|
|||||||
// Replace System parentheses (used to keep layout tree structure) by normal parentheses
|
// Replace System parentheses (used to keep layout tree structure) by normal parentheses
|
||||||
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(buffer);
|
Poincare::SerializationHelper::ReplaceSystemParenthesesByUserParentheses(buffer);
|
||||||
|
|
||||||
if (insertTextAtLocation(buffer, const_cast<char *>(cursorLocation()))) {
|
int textLength = strlen(buffer);
|
||||||
|
if (contentView()->isAbleToInsertTextAt(textLength, cursorLocation(), shouldRemoveLastCharacter)) {
|
||||||
|
if (shouldRemoveLastCharacter) {
|
||||||
|
removePreviousGlyph();
|
||||||
|
}
|
||||||
|
|
||||||
|
insertTextAtLocation(buffer, const_cast<char *>(cursorLocation()), textLength);
|
||||||
/* The cursor position depends on the text as we sometimes want to position
|
/* 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
|
* the cursor at the end of the text and sometimes after the first
|
||||||
* parenthesis. */
|
* parenthesis. */
|
||||||
|
|||||||
@@ -170,15 +170,13 @@ void TextInput::setAlignment(float horizontalAlignment, float verticalAlignment)
|
|||||||
contentView()->setAlignment(horizontalAlignment, verticalAlignment);
|
contentView()->setAlignment(horizontalAlignment, verticalAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextInput::insertTextAtLocation(const char * text, char * location) {
|
void TextInput::insertTextAtLocation(const char * text, char * location, int textLength) {
|
||||||
if (contentView()->insertTextAtLocation(text, location)) {
|
assert(contentView()->isAbleToInsertTextAt(textLength, location, false));
|
||||||
/* We layout the scrollable view before scrolling to cursor because the
|
contentView()->insertTextAtLocation(text, location, textLength);
|
||||||
* content size might have changed. */
|
/* We layout the scrollable view before scrolling to cursor because the
|
||||||
layoutSubviews();
|
* content size might have changed. */
|
||||||
scrollToCursor();
|
layoutSubviews();
|
||||||
return true;
|
scrollToCursor();
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextInput::removeEndOfLine() {
|
bool TextInput::removeEndOfLine() {
|
||||||
|
|||||||
Reference in New Issue
Block a user