From 4064dcd5d38b5f11be7102378e3502bc12925403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 4 Oct 2016 13:36:03 +0200 Subject: [PATCH] [escher] create a class input view controller Change-Id: Ibd85039b9d24bceef012414ff18d0bd92e710331 --- escher/Makefile | 1 + escher/include/escher.h | 1 + escher/include/escher/input_view_controller.h | 42 +++++++ escher/src/input_view_controller.cpp | 115 ++++++++++++++++++ 4 files changed, 159 insertions(+) create mode 100644 escher/include/escher/input_view_controller.h create mode 100644 escher/src/input_view_controller.cpp diff --git a/escher/Makefile b/escher/Makefile index 5889d1ed6..dc699f02b 100644 --- a/escher/Makefile +++ b/escher/Makefile @@ -6,6 +6,7 @@ objs += $(addprefix escher/src/,\ container.o\ image_view.o\ invocation.o\ + input_view_controller.o\ list_view.o\ metric.o\ palette.o\ diff --git a/escher/include/escher.h b/escher/include/escher.h index a071a4f9e..06621993c 100644 --- a/escher/include/escher.h +++ b/escher/include/escher.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/escher/include/escher/input_view_controller.h b/escher/include/escher/input_view_controller.h new file mode 100644 index 000000000..877f305f9 --- /dev/null +++ b/escher/include/escher/input_view_controller.h @@ -0,0 +1,42 @@ +#ifndef ESCHER_INPUT_VIEW_CONTROLLER_H +#define ESCHER_INPUT_VIEW_CONTROLLER_H + +#include +#include +#include + +class InputViewController : public ViewController { +public: + InputViewController(Responder * parentResponder, ViewController * child); + View * view() override; + const char * title() const override; + + bool handleEvent(Ion::Events::Event event) override; + void edit(Responder * caller, const char * initialContent, void * context, Invocation::Action successAction, Invocation::Action failureAction); + const char * textBody(); +private: + class ContentView : public View { + public: + ContentView(View * subview); + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + void setVisibleInput(bool showInput); + TextField * textField(); + private: + static constexpr KDCoordinate k_textFieldHeight = 20; + View * m_mainView; + TextField m_textField; + bool m_visibleInput; + char m_textBody[255]; + }; + void showInput(bool show); + void setTextBody(const char * text); + void setPreviousResponder(Responder * previousResponder); + ContentView m_contentView; + Responder * m_previousResponder; + Invocation m_successAction; + Invocation m_failureAction; +}; + +#endif diff --git a/escher/src/input_view_controller.cpp b/escher/src/input_view_controller.cpp new file mode 100644 index 000000000..8cf007a06 --- /dev/null +++ b/escher/src/input_view_controller.cpp @@ -0,0 +1,115 @@ +#include +#include +#include + +InputViewController::ContentView::ContentView(View * subview) : + View(), + m_mainView(subview), + m_textField(nullptr, m_textBody, 255), + m_visibleInput(false) +{ + m_textBody[0] = 0; +} + +int InputViewController::ContentView::numberOfSubviews() const { + if (m_visibleInput) { + return 2; + } + return 1; +} + +View * InputViewController::ContentView::subviewAtIndex(int index) { + switch (index) { + case 0: + return m_mainView; + case 1: + if (numberOfSubviews() == 2) { + return &m_textField; + } else { + assert(false); + } + default: + assert(false); + } +} + +void InputViewController::ContentView::layoutSubviews() { + m_mainView->setFrame(bounds()); + if (numberOfSubviews() == 2) { + KDRect inputView(0, bounds().height() - k_textFieldHeight, bounds().width(), k_textFieldHeight); + m_textField.setFrame(inputView); + } +} + +void InputViewController::ContentView::setVisibleInput(bool showInput) { + m_visibleInput = showInput; + markRectAsDirty(KDRect(0, bounds().height() - k_textFieldHeight, bounds().width(), k_textFieldHeight)); + layoutSubviews(); +} + +TextField * InputViewController::ContentView::textField() { + return &m_textField; +} + +InputViewController::InputViewController(Responder * parentResponder, ViewController * child) : + ViewController(parentResponder), + m_contentView(child->view()), + m_previousResponder(nullptr), + m_successAction(Invocation(nullptr, nullptr)), + m_failureAction(Invocation(nullptr, nullptr)) +{ + m_contentView.textField()->setParentResponder(this); +} + +View * InputViewController::view() { + return &m_contentView; +} + +const char * InputViewController::title() const { + return "InputViewController"; +} + +const char * InputViewController::textBody() { + return m_contentView.textField()->textBuffer(); +} + +void InputViewController::setPreviousResponder(Responder * previousResponder) { + m_previousResponder = previousResponder; +} + +void InputViewController::showInput(bool show) { + m_contentView.setVisibleInput(show); + if (show) { + m_previousResponder = app()->firstResponder(); + app()->setFirstResponder(m_contentView.textField()); + } else { + app()->setFirstResponder(m_previousResponder); + } +} + +void InputViewController::setTextBody(const char * text) { + m_contentView.textField()->setTextBuffer(text); +} + +bool InputViewController::handleEvent(Ion::Events::Event event) { + switch (event) { + case Ion::Events::Event::ENTER: + m_successAction.perform(this); + showInput(false); + return true; + case Ion::Events::Event::ESC: + m_failureAction.perform(this); + showInput(false); + return true; + default: + return false; + } +} + +void InputViewController::edit(Responder * caller, const char * initialContent, void * context, Invocation::Action successAction, Invocation::Action failureAction) { + m_successAction = Invocation(successAction, context); + m_failureAction = Invocation(failureAction, context); + setPreviousResponder(caller); + setTextBody(initialContent); + showInput(true); +}