From d2b2705d2d5be363a70c52944928e9605b5321e6 Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Fri, 1 Jun 2018 17:01:36 +0200 Subject: [PATCH] [escher] TextInput doesn't use colors anymore --- apps/code/editor_view.h | 4 +- escher/Makefile | 1 + escher/include/escher/solid_text_area.h | 30 +++++++++ escher/include/escher/text_area.h | 32 ++++++---- escher/include/escher/text_field.h | 7 +++ escher/include/escher/text_input.h | 9 +-- escher/src/solid_text_area.cpp | 43 +++++++++++++ escher/src/text_area.cpp | 83 +++++++------------------ escher/src/text_field.cpp | 25 +++++++- escher/src/text_input.cpp | 23 +------ 10 files changed, 151 insertions(+), 106 deletions(-) create mode 100644 escher/include/escher/solid_text_area.h create mode 100644 escher/src/solid_text_area.cpp diff --git a/apps/code/editor_view.h b/apps/code/editor_view.h index 2b268353b..efe06cac5 100644 --- a/apps/code/editor_view.h +++ b/apps/code/editor_view.h @@ -2,7 +2,7 @@ #define CODE_EDITOR_VIEW_H #include -#include +#include class EditorView : public Responder, public View, public ScrollViewDelegate { public: @@ -38,7 +38,7 @@ private: KDCoordinate m_offset; }; - TextArea m_textArea; + SolidTextArea m_textArea; GutterView m_gutterView; }; diff --git a/escher/Makefile b/escher/Makefile index aa6865b1c..237f6ed2f 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -58,6 +58,7 @@ objs += $(addprefix escher/src/,\ simple_list_view_data_source.o\ simple_table_view_data_source.o\ solid_color_view.o\ + solid_text_area.o\ stack_view.o\ stack_view_controller.o\ switch_view.o\ diff --git a/escher/include/escher/solid_text_area.h b/escher/include/escher/solid_text_area.h new file mode 100644 index 000000000..14c75a45b --- /dev/null +++ b/escher/include/escher/solid_text_area.h @@ -0,0 +1,30 @@ +#ifndef ESCHER_SOLID_TEXT_AREA_H +#define ESCHER_SOLID_TEXT_AREA_H + +#include + +/* SimpleTextArea is a text area that draws text in a single solid color over a + * solid background. */ + +class SolidTextArea : public TextArea { +public: + SolidTextArea(Responder * parentResponder, KDText::FontSize fontSize = KDText::FontSize::Large, + KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite) : + TextArea(parentResponder, &m_contentView, fontSize), + m_contentView(fontSize, textColor, backgroundColor) {} +protected: + class ContentView : public TextArea::ContentView { + public: + ContentView(KDText::FontSize size, KDColor textColor, KDColor backgroundColor); + void drawRect(KDContext * ctx, KDRect rect) const override; + private: + KDColor m_textColor; + KDColor m_backgroundColor; + }; + +private: + const ContentView * nonEditableContentView() const override { return &m_contentView; } + ContentView m_contentView; +}; + +#endif diff --git a/escher/include/escher/text_area.h b/escher/include/escher/text_area.h index 562a21dce..a03636c55 100644 --- a/escher/include/escher/text_area.h +++ b/escher/include/escher/text_area.h @@ -8,23 +8,25 @@ class TextArea : public TextInput { public: - TextArea(Responder * parentResponder, char * textBuffer = nullptr, size_t textBufferSize = 0, TextAreaDelegate * delegate = nullptr, KDText::FontSize fontSize = KDText::FontSize::Large, - KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); + TextArea(Responder * parentResponder, View * contentView, KDText::FontSize fontSize = KDText::FontSize::Large); void setDelegate(TextAreaDelegate * delegate) { m_delegate = delegate; } bool handleEvent(Ion::Events::Event event) override; bool handleEventWithText(const char * text, bool indentation = false, bool forceCursorRightOfText = false) override; void setText(char * textBuffer, size_t textBufferSize); -private: + +protected: int indentationBeforeCursor() const; bool insertTextWithIndentation(const char * textBuffer, int location); TextInputDelegate * delegate() override { return m_delegate; } + class Text { public: Text(char * buffer, size_t bufferSize); void setText(char * buffer, size_t bufferSize); const char * text() const { return const_cast(m_buffer); } + class Line { public: Line(const char * text); @@ -84,28 +86,34 @@ private: class ContentView : public TextInput::ContentView { public: - ContentView(char * textBuffer, size_t textBufferSize, KDText::FontSize size, - KDColor textColor, KDColor backgroundColor); - void drawRect(KDContext * ctx, KDRect rect) const override; + ContentView(KDText::FontSize fontSize); KDSize minimalSizeForOptimalDisplay() const override; void setText(char * textBuffer, size_t textBufferSize); const char * text() const override; + size_t editedTextLength() const override; const Text * getText() const { return &m_text; } - size_t editedTextLength() const override { - return m_text.textLength(); - } bool insertTextAtLocation(const char * text, int location) override; void moveCursorGeo(int deltaX, int deltaY); bool removeChar() override; bool removeEndOfLine() override; bool removeStartOfLine(); - private: + protected: KDRect characterFrameAtIndex(size_t index) const override; Text m_text; }; - const ContentView * nonEditableContentView() const override { return &m_contentView; } - ContentView m_contentView; + + ContentView * contentView() { return static_cast(TextInput::contentView()); } +private: TextAreaDelegate * m_delegate; }; +/* +class TextAreaConcrete : public TextArea { +public: + TextAreaConcrete(Responder * parentResponder) : TextArea(parentResponder), m_contentView( {} +private: + const ContentView * nonEditableContentView() const override { return &m_contentView; } + ContentView m_contentView; +}; +*/ #endif diff --git a/escher/include/escher/text_field.h b/escher/include/escher/text_field.h index 23f366b10..b6a2bbf03 100644 --- a/escher/include/escher/text_field.h +++ b/escher/include/escher/text_field.h @@ -10,6 +10,8 @@ public: TextField(Responder * parentResponder, char * textBuffer, char * draftTextBuffer, size_t textBufferSize, TextFieldDelegate * delegate = nullptr, bool hasTwoBuffers = true, KDText::FontSize size = KDText::FontSize::Large, float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor backgroundColor = KDColorWhite); + void setBackgroundColor(KDColor backgroundColor) override; + void setTextColor(KDColor textColor); void setDelegate(TextFieldDelegate * delegate) { m_delegate = delegate; } void setDraftTextBuffer(char * draftTextBuffer); bool isEditing() const; @@ -29,6 +31,9 @@ protected: class ContentView : public TextInput::ContentView { public: ContentView(char * textBuffer, char * draftTextBuffer, size_t textBufferSize, KDText::FontSize size, float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite); + void setBackgroundColor(KDColor backgroundColor); + KDColor backgroundColor() const { return m_backgroundColor; } + void setTextColor(KDColor textColor); void setDraftTextBuffer(char * draftTextBuffer); void drawRect(KDContext * ctx, KDRect rect) const override; bool isEditing() const { return m_isEditing; } @@ -64,6 +69,8 @@ protected: size_t m_textBufferSize; float m_horizontalAlignment; float m_verticalAlignment; + KDColor m_textColor; + KDColor m_backgroundColor; }; const ContentView * nonEditableContentView() const override { return &m_contentView; } ContentView m_contentView; diff --git a/escher/include/escher/text_input.h b/escher/include/escher/text_input.h index 513386659..085687313 100644 --- a/escher/include/escher/text_input.h +++ b/escher/include/escher/text_input.h @@ -12,8 +12,6 @@ public: TextInput(Responder * parentResponder, View * contentView); Toolbox * toolbox() override; const char * text() const { return nonEditableContentView()->text(); } - void setBackgroundColor(KDColor backgroundColor) override; - void setTextColor(KDColor textColor); bool removeChar(); size_t cursorLocation() const { return nonEditableContentView()->cursorLocation(); } bool setCursorLocation(int location); @@ -21,10 +19,7 @@ public: protected: class ContentView : public View { public: - ContentView(KDText::FontSize size, KDColor textColor, KDColor backgroundColor); - void setBackgroundColor(KDColor backgroundColor); - KDColor backgroundColor() const { return m_backgroundColor; } - void setTextColor(KDColor textColor); + ContentView(KDText::FontSize size); size_t cursorLocation() const { return m_cursorIndex; } void setCursorLocation(int cursorLocation); virtual const char * text() const = 0; @@ -38,8 +33,6 @@ protected: virtual KDRect characterFrameAtIndex(size_t index) const = 0; TextCursorView m_cursorView; KDText::FontSize m_fontSize; - KDColor m_textColor; - KDColor m_backgroundColor; size_t m_cursorIndex; private: int numberOfSubviews() const override; diff --git a/escher/src/solid_text_area.cpp b/escher/src/solid_text_area.cpp new file mode 100644 index 000000000..30ffb3e65 --- /dev/null +++ b/escher/src/solid_text_area.cpp @@ -0,0 +1,43 @@ +#include + +SolidTextArea::ContentView::ContentView(KDText::FontSize size, KDColor textColor, KDColor backgroundColor) : + TextArea::ContentView(size), + m_textColor(textColor), + m_backgroundColor(backgroundColor) +{ +} + +void SolidTextArea::ContentView::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect(rect, m_backgroundColor); + + KDSize charSize = KDText::charSize(m_fontSize); + + // We want to draw even partially visible characters. So we need to round + // down for the top left corner and up for the bottom right one. + Text::Position topLeft( + rect.x()/charSize.width(), + rect.y()/charSize.height() + ); + Text::Position bottomRight( + rect.right()/charSize.width() + 1, + rect.bottom()/charSize.height() + 1 + ); + + int y = 0; + size_t x = topLeft.column(); + + for (Text::Line line : m_text) { + if (y >= topLeft.line() && y <= bottomRight.line() && topLeft.column() < (int)line.length()) { + //drawString(line.text(), 0, y*charHeight); // Naive version + ctx->drawString( + line.text() + topLeft.column(), + KDPoint(x*charSize.width(), y*charSize.height()), + m_fontSize, + m_textColor, + m_backgroundColor, + min(line.length() - topLeft.column(), bottomRight.column() - topLeft.column()) + ); + } + y++; + } +} diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp index f68e911a8..18bf65ee6 100644 --- a/escher/src/text_area.cpp +++ b/escher/src/text_area.cpp @@ -6,7 +6,6 @@ #include #include - static inline size_t min(size_t a, size_t b) { return (a>b ? b : a); } @@ -150,9 +149,9 @@ TextArea::Text::Position TextArea::Text::span() const { /* TextArea::ContentView */ -TextArea::ContentView::ContentView(char * textBuffer, size_t textBufferSize, KDText::FontSize fontSize, KDColor textColor, KDColor backgroundColor) : - TextInput::ContentView(fontSize, textColor, backgroundColor), - m_text(textBuffer, textBufferSize) +TextArea::ContentView::ContentView(KDText::FontSize fontSize) : + TextInput::ContentView(fontSize), + m_text(nullptr, 0) { } @@ -167,42 +166,6 @@ KDSize TextArea::ContentView::minimalSizeForOptimalDisplay() const { ); } - -void TextArea::ContentView::drawRect(KDContext * ctx, KDRect rect) const { - ctx->fillRect(rect, m_backgroundColor); - - KDSize charSize = KDText::charSize(m_fontSize); - - // We want to draw even partially visible characters. So we need to round - // down for the top left corner and up for the bottom right one. - Text::Position topLeft( - rect.x()/charSize.width(), - rect.y()/charSize.height() - ); - Text::Position bottomRight( - rect.right()/charSize.width() + 1, - rect.bottom()/charSize.height() + 1 - ); - - int y = 0; - size_t x = topLeft.column(); - - for (Text::Line line : m_text) { - if (y >= topLeft.line() && y <= bottomRight.line() && topLeft.column() < (int)line.length()) { - //drawString(line.text(), 0, y*charHeight); // Naive version - ctx->drawString( - line.text() + topLeft.column(), - KDPoint(x*charSize.width(), y*charSize.height()), - m_fontSize, - m_textColor, - m_backgroundColor, - min(line.length() - topLeft.column(), bottomRight.column() - topLeft.column()) - ); - } - y++; - } -} - void TextArea::TextArea::ContentView::setText(char * textBuffer, size_t textBufferSize) { m_text.setText(textBuffer, textBufferSize); m_cursorIndex = 0; @@ -239,6 +202,10 @@ bool TextArea::TextArea::ContentView::removeChar() { return true; } +size_t TextArea::ContentView::editedTextLength() const { + return m_text.textLength(); +} + bool TextArea::ContentView::removeEndOfLine() { size_t removedLine = m_text.removeRemainingLine(cursorLocation(), 1); if (removedLine > 0) { @@ -263,7 +230,7 @@ bool TextArea::ContentView::removeStartOfLine() { return false; } -KDRect TextArea::TextArea::ContentView::characterFrameAtIndex(size_t index) const { +KDRect TextArea::ContentView::characterFrameAtIndex(size_t index) const { KDSize charSize = KDText::charSize(m_fontSize); Text::Position p = m_text.positionAtIndex(index); return KDRect( @@ -274,21 +241,17 @@ KDRect TextArea::TextArea::ContentView::characterFrameAtIndex(size_t index) cons ); } -void TextArea::TextArea::ContentView::moveCursorGeo(int deltaX, int deltaY) { +void TextArea::ContentView::moveCursorGeo(int deltaX, int deltaY) { Text::Position p = m_text.positionAtIndex(m_cursorIndex); setCursorLocation(m_text.indexAtPosition(Text::Position(p.column() + deltaX, p.line() + deltaY))); } /* TextArea */ -TextArea::TextArea(Responder * parentResponder, char * textBuffer, - size_t textBufferSize, TextAreaDelegate * delegate, - KDText::FontSize fontSize, KDColor textColor, KDColor backgroundColor) : - TextInput(parentResponder, &m_contentView), - m_contentView(textBuffer, textBufferSize, fontSize, textColor, backgroundColor), - m_delegate(delegate) +TextArea::TextArea(Responder * parentResponder, View * contentView, KDText::FontSize fontSize) : + TextInput(parentResponder, contentView), + m_delegate(nullptr) { - assert(textBufferSize < INT_MAX/2); } bool TextArea::handleEventWithText(const char * text, bool indentation, bool forceCursorRightOfText) { @@ -331,13 +294,13 @@ bool TextArea::handleEvent(Ion::Events::Event event) { } else if (event == Ion::Events::Right) { return setCursorLocation(cursorLocation()+1); } else if (event == Ion::Events::Up) { - m_contentView.moveCursorGeo(0, -1); + contentView()->moveCursorGeo(0, -1); } else if (event == Ion::Events::Down) { - m_contentView.moveCursorGeo(0, 1); + contentView()->moveCursorGeo(0, 1); } else if (event == Ion::Events::ShiftLeft) { - m_contentView.moveCursorGeo(-INT_MAX/2, 0); + contentView()->moveCursorGeo(-INT_MAX/2, 0); } else if (event == Ion::Events::ShiftRight) { - m_contentView.moveCursorGeo(INT_MAX/2, 0); + contentView()->moveCursorGeo(INT_MAX/2, 0); } else if (event == Ion::Events::Backspace) { return removeChar(); } else if (event.hasText()) { @@ -345,8 +308,8 @@ bool TextArea::handleEvent(Ion::Events::Event event) { } else if (event == Ion::Events::EXE) { return handleEventWithText("\n"); } else if (event == Ion::Events::Clear) { - if (!m_contentView.removeEndOfLine()) { - m_contentView.removeStartOfLine(); + if (!contentView()->removeEndOfLine()) { + contentView()->removeStartOfLine(); } } else if (event == Ion::Events::Paste) { return handleEventWithText(Clipboard::sharedClipboard()->storedText()); @@ -358,8 +321,8 @@ bool TextArea::handleEvent(Ion::Events::Event event) { } void TextArea::setText(char * textBuffer, size_t textBufferSize) { - m_contentView.setText(textBuffer, textBufferSize); - m_contentView.moveCursorGeo(0, 0); + contentView()->setText(textBuffer, textBufferSize); + contentView()->moveCursorGeo(0, 0); } bool TextArea::insertTextWithIndentation(const char * textBuffer, int location) { @@ -377,7 +340,7 @@ bool TextArea::insertTextWithIndentation(const char * textBuffer, int location) totalIndentationSize+=spaceStringSize; } } - if (m_contentView.getText()->textLength() + textSize + totalIndentationSize >= m_contentView.getText()->bufferSize() || textSize == 0) { + if (contentView()->getText()->textLength() + textSize + totalIndentationSize >= contentView()->getText()->bufferSize() || textSize == 0) { return false; } int currentLocation = location; @@ -395,8 +358,8 @@ bool TextArea::insertTextWithIndentation(const char * textBuffer, int location) int TextArea::indentationBeforeCursor() const { int charIndex = cursorLocation()-1; int indentationSize = 0; - while (charIndex >= 0 && m_contentView.text()[charIndex] != '\n') { - if (m_contentView.text()[charIndex] == ' ') { + while (charIndex >= 0 && nonEditableContentView()->text()[charIndex] != '\n') { + if (nonEditableContentView()->text()[charIndex] == ' ') { indentationSize++; } else { indentationSize = 0; diff --git a/escher/src/text_field.cpp b/escher/src/text_field.cpp index b40174b62..353973451 100644 --- a/escher/src/text_field.cpp +++ b/escher/src/text_field.cpp @@ -7,18 +7,30 @@ /* TextField::ContentView */ TextField::ContentView::ContentView(char * textBuffer, char * draftTextBuffer, size_t textBufferSize, KDText::FontSize size, float horizontalAlignment, float verticalAlignment, KDColor textColor, KDColor backgroundColor) : - TextInput::ContentView(size, textColor, backgroundColor), + TextInput::ContentView(size), m_isEditing(false), m_textBuffer(textBuffer), m_draftTextBuffer(draftTextBuffer), m_currentDraftTextLength(0), m_textBufferSize(textBufferSize), m_horizontalAlignment(horizontalAlignment), - m_verticalAlignment(verticalAlignment) + m_verticalAlignment(verticalAlignment), + m_textColor(textColor), + m_backgroundColor(backgroundColor) { assert(m_textBufferSize <= k_maxBufferSize); } +void TextField::ContentView::setBackgroundColor(KDColor backgroundColor) { + m_backgroundColor = backgroundColor; + markRectAsDirty(bounds()); +} + +void TextField::ContentView::setTextColor(KDColor textColor) { + m_textColor = textColor; + markRectAsDirty(bounds()); +} + void TextField::ContentView::setDraftTextBuffer(char * draftTextBuffer) { m_draftTextBuffer = draftTextBuffer; } @@ -169,6 +181,15 @@ TextField::TextField(Responder * parentResponder, char * textBuffer, char * draf { } +void TextField::setBackgroundColor(KDColor backgroundColor) { + ScrollView::setBackgroundColor(backgroundColor); + m_contentView.setBackgroundColor(backgroundColor); +} + +void TextField::setTextColor(KDColor textColor) { + m_contentView.setTextColor(textColor); +} + void TextField::setDraftTextBuffer(char * draftTextBuffer) { m_contentView.setDraftTextBuffer(draftTextBuffer); } diff --git a/escher/src/text_input.cpp b/escher/src/text_input.cpp index 4e27d0c41..a4ee5b7d7 100644 --- a/escher/src/text_input.cpp +++ b/escher/src/text_input.cpp @@ -3,26 +3,14 @@ /* TextInput::ContentView */ -TextInput::ContentView::ContentView(KDText::FontSize size, KDColor textColor, KDColor backgroundColor) : +TextInput::ContentView::ContentView(KDText::FontSize size) : View(), m_cursorView(), m_fontSize(size), - m_textColor(textColor), - m_backgroundColor(backgroundColor), m_cursorIndex(0) { } -void TextInput::ContentView::setBackgroundColor(KDColor backgroundColor) { - m_backgroundColor = backgroundColor; - markRectAsDirty(bounds()); -} - -void TextInput::ContentView::setTextColor(KDColor textColor) { - m_textColor = textColor; - markRectAsDirty(bounds()); -} - void TextInput::ContentView::setCursorLocation(int location) { int adjustedLocation = location < 0 ? 0 : location; adjustedLocation = adjustedLocation > (signed int)editedTextLength() ? (signed int)editedTextLength() : adjustedLocation; @@ -69,15 +57,6 @@ Toolbox * TextInput::toolbox() { return nullptr; } -void TextInput::setBackgroundColor(KDColor backgroundColor) { - ScrollView::setBackgroundColor(backgroundColor); - contentView()->setBackgroundColor(backgroundColor); -} - -void TextInput::setTextColor(KDColor textColor) { - contentView()->setTextColor(textColor); -} - bool TextInput::removeChar() { contentView()->removeChar(); scrollToCursor();