mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
212 lines
5.9 KiB
C++
212 lines
5.9 KiB
C++
#include <escher/text_field.h>
|
|
#include <assert.h>
|
|
|
|
TextField::TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer,
|
|
size_t textBufferSize, TextFieldDelegate * delegate, KDText::FontSize size,
|
|
float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor) :
|
|
View(),
|
|
Responder(parentResponder),
|
|
m_isEditing(false),
|
|
m_textBuffer(textBuffer),
|
|
m_draftTextBuffer(draftTextBuffer),
|
|
m_currentTextLength(0),
|
|
m_currentCursorLocation(0),
|
|
m_textBufferSize(textBufferSize),
|
|
m_delegate(delegate),
|
|
m_horizontalAlignment(horizontalAlignment),
|
|
m_verticalAlignment(verticalAlignment),
|
|
m_textColor(textColor),
|
|
m_backgroundColor(backgroundColor),
|
|
m_fontSize(size)
|
|
{
|
|
}
|
|
|
|
Toolbox * TextField::toolbox() {
|
|
if (m_delegate) {
|
|
return m_delegate->toolboxForTextField(this);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
const char * TextField::text() const {
|
|
if (m_isEditing) {
|
|
return (const char *)m_draftTextBuffer;
|
|
}
|
|
return (const char *)m_textBuffer;
|
|
}
|
|
|
|
void TextField::drawRect(KDContext * ctx, KDRect rect) const {
|
|
ctx->fillRect(rect, m_backgroundColor);
|
|
KDSize textSize = KDText::stringSize(text(), m_fontSize);
|
|
KDPoint origin(m_horizontalAlignment*(m_frame.width() - textSize.width()),
|
|
m_verticalAlignment*(m_frame.height() - textSize.height()));
|
|
ctx->drawString(text(), origin, m_fontSize, m_textColor, m_backgroundColor);
|
|
}
|
|
|
|
#if ESCHER_VIEW_LOGGING
|
|
const char * TextField::className() const {
|
|
return "TextField";
|
|
}
|
|
#endif
|
|
|
|
void TextField::setBackgroundColor(KDColor backgroundColor) {
|
|
m_backgroundColor = backgroundColor;
|
|
markRectAsDirty(bounds());
|
|
}
|
|
|
|
void TextField::setTextColor(KDColor textColor) {
|
|
m_textColor = textColor;
|
|
markRectAsDirty(bounds());
|
|
}
|
|
|
|
void TextField::setAlignment(float horizontalAlignment, float verticalAlignment) {
|
|
m_horizontalAlignment = horizontalAlignment;
|
|
m_verticalAlignment = verticalAlignment;
|
|
markRectAsDirty(bounds());
|
|
}
|
|
|
|
void TextField::reload() {
|
|
KDSize textSize = KDText::stringSize(text(), m_fontSize);
|
|
KDPoint origin(m_horizontalAlignment*(m_frame.width() - textSize.width()),
|
|
m_verticalAlignment*(m_frame.height() - textSize.height()));
|
|
KDRect dirtyZone(origin, textSize);
|
|
markRectAsDirty(dirtyZone);
|
|
}
|
|
|
|
bool TextField::handleEvent(Ion::Events::Event event) {
|
|
if (Responder::handleEvent(event)) {
|
|
return true;
|
|
}
|
|
if (m_delegate) {
|
|
if (m_delegate->textFieldDidReceiveEvent(this, event)) {
|
|
return true;
|
|
}
|
|
}
|
|
if (event == Ion::Events::OK) {
|
|
if (m_isEditing) {
|
|
strlcpy(m_textBuffer, m_draftTextBuffer, m_textBufferSize);
|
|
setEditing(false);
|
|
m_delegate->textFieldDidFinishEditing(this, text());
|
|
return true;
|
|
}
|
|
setEditing(true);
|
|
insertTextAtLocation(m_textBuffer, cursorLocation());
|
|
setCursorLocation(strlen(m_draftTextBuffer));
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::Left && m_isEditing) {
|
|
if (m_currentCursorLocation > 0) {
|
|
m_currentCursorLocation--;
|
|
}
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::Right && m_isEditing) {
|
|
if (m_currentCursorLocation < m_currentTextLength) {
|
|
m_currentCursorLocation++;
|
|
}
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::Backspace && m_isEditing) {
|
|
if (m_currentCursorLocation > 0) {
|
|
reload();
|
|
m_currentTextLength--;
|
|
m_currentCursorLocation--;
|
|
for (int k = m_currentCursorLocation; k < (signed char)m_currentTextLength; k ++) {
|
|
m_draftTextBuffer[k] = m_draftTextBuffer[k+1];
|
|
}
|
|
m_draftTextBuffer[m_currentTextLength] = 0;
|
|
}
|
|
return true;
|
|
}
|
|
if (event.hasText()) {
|
|
if (m_isEditing) {
|
|
insertTextAtLocation(event.text(), cursorLocation());
|
|
} else {
|
|
setEditing(true);
|
|
insertTextAtLocation(event.text(), cursorLocation());
|
|
}
|
|
int cursorDelta = strlen(event.text()) > 1 ? -1 : 0;
|
|
setCursorLocation(cursorLocation() + strlen(event.text()) + cursorDelta);
|
|
return true;
|
|
}
|
|
if (event == Ion::Events::Back && m_isEditing) {
|
|
m_delegate->textFieldDidAbortEditing(this, text());
|
|
setEditing(false);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int TextField::textLength() const {
|
|
assert(strlen(text()) == m_currentTextLength);
|
|
return m_currentTextLength;
|
|
}
|
|
|
|
void TextField::setText(const char * text) {
|
|
reload();
|
|
if (m_isEditing) {
|
|
strlcpy(m_draftTextBuffer, text, m_textBufferSize);
|
|
m_currentCursorLocation = strlen(text);
|
|
m_currentTextLength = m_currentCursorLocation;
|
|
} else {
|
|
strlcpy(m_textBuffer, text, m_textBufferSize);
|
|
}
|
|
reload();
|
|
}
|
|
|
|
int TextField::cursorLocation() const{
|
|
return m_currentCursorLocation;
|
|
}
|
|
|
|
void TextField::setCursorLocation(int location) {
|
|
location = location < 0 ? 0 : location;
|
|
location = location > (signed char)m_currentTextLength ? m_currentTextLength : location;
|
|
m_currentCursorLocation = location;
|
|
}
|
|
|
|
void TextField::insertTextAtLocation(const char * text, int location) {
|
|
int textSize = strlen(text);
|
|
if (m_currentTextLength + textSize > m_textBufferSize) {
|
|
return;
|
|
}
|
|
for (int k = m_currentTextLength; k >= location && k >= 0; k--) {
|
|
m_draftTextBuffer[k+textSize] = m_draftTextBuffer[k];
|
|
}
|
|
strlcpy(&m_draftTextBuffer[location], text, textSize);
|
|
if (location+textSize > 0) {
|
|
m_draftTextBuffer[location+textSize-1] = text[textSize-1];
|
|
}
|
|
m_currentTextLength += textSize;
|
|
reload();
|
|
}
|
|
|
|
KDSize TextField::minimalSizeForOptimalDisplay() {
|
|
KDSize textSize = KDText::stringSize(m_draftTextBuffer, m_fontSize);
|
|
return KDSize(0, textSize.height());
|
|
}
|
|
|
|
void TextField::setTextFieldDelegate(TextFieldDelegate * delegate) {
|
|
m_delegate = delegate;
|
|
}
|
|
|
|
bool TextField::isEditing() const {
|
|
return m_isEditing;
|
|
}
|
|
|
|
void TextField::setEditing(bool isEditing) {
|
|
if (m_isEditing == isEditing) {
|
|
return;
|
|
}
|
|
if (m_isEditing == false) {
|
|
reinitDraftTextBuffer();
|
|
}
|
|
m_isEditing = isEditing;
|
|
markRectAsDirty(bounds());
|
|
}
|
|
|
|
void TextField::reinitDraftTextBuffer() {
|
|
setCursorLocation(0);
|
|
m_draftTextBuffer[0] = 0;
|
|
m_currentTextLength = 0;
|
|
}
|