Add Event.

This commit is contained in:
Arthur Sonzogni
2018-10-18 22:58:38 +02:00
parent 1a4b2c98b2
commit f94b63fafb
25 changed files with 273 additions and 76 deletions

View File

@@ -6,6 +6,7 @@ add_library(ftxui
src/ftxui/component/component_direction.cpp
src/ftxui/component/component_horizontal.cpp
src/ftxui/component/component_vertical.cpp
src/ftxui/component/input.cpp
src/ftxui/component/menu.cpp
src/ftxui/component/toggle.cpp
src/ftxui/dom/bold.cpp
@@ -14,7 +15,6 @@ add_library(ftxui
src/ftxui/dom/dim.cpp
src/ftxui/dom/flex.cpp
src/ftxui/dom/frame.cpp
src/ftxui/dom/frame.cpp
src/ftxui/dom/gauge.cpp
src/ftxui/dom/hbox.cpp
src/ftxui/dom/inverted.cpp
@@ -24,6 +24,7 @@ add_library(ftxui
src/ftxui/dom/text.cpp
src/ftxui/dom/underlined.cpp
src/ftxui/dom/vbox.cpp
src/ftxui/event.cpp
src/ftxui/screen.cpp
src/ftxui/screen_interactive.cpp
src/ftxui/terminal.cpp

View File

@@ -1,34 +0,0 @@
#ifndef FTXUI_COMPONENT_EVENT
#define FTXUI_COMPONENT_EVENT
namespace ftxui {
namespace component {
struct Event{
// --- Character ---
static Event Character(char);
// --- Arrow ---
static Event Arrow_Left;
static Event Arrow_Right;
static Event Arrow_Up;
static Event Arrow_Down;
// --- Other ---
static Event Backspace;
static Event Delete;
static Event Escape;
static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
// Internal representation.
int values [3];
Event(int values[3]) : values(values);
};
} // namespace component
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_EVENT */

View File

@@ -1,8 +1,9 @@
#ifndef FTXUI_COMPONENT_COMPONENT_HPP
#define FTXUI_COMPONENT_COMPONENT_HPP
#include "ftxui/dom/elements.hpp"
#include "ftxui/component/delegate.hpp"
#include "ftxui/dom/elements.hpp"
#include "ftxui/event.hpp"
namespace ftxui {
namespace component {
@@ -20,7 +21,7 @@ class Component {
virtual dom::Element Render();
// Handle an event. By default, it calls this function on each children.
virtual bool Event(int key);
virtual bool OnEvent(Event even);
// If this component contains children, this indicates which one is active. It
// can be none of them.

View File

@@ -10,12 +10,12 @@ namespace component {
class ComponentDirection : public Component {
public:
ComponentDirection(Delegate* delegate);
bool Event(int key) override;
bool OnEvent(Event) override;
Component* GetActiveChild() override;
protected:
void Focus(Component* child);
virtual bool HandleDirection(int key) = 0;
virtual bool HandleDirection(Event) = 0;
Component* active_child_;
};

View File

@@ -10,8 +10,8 @@ namespace component {
// It assumes its children are put in the horizontal direction.
class ComponentHorizontal : public ComponentDirection {
public:
ComponentHorizontal(Delegate* delegate);
bool HandleDirection(int key) override;
ComponentHorizontal(Delegate*);
bool HandleDirection(Event) override;
};
} // namespace component

View File

@@ -10,8 +10,8 @@ namespace component {
// It assumes its children are put in the vertical direction.
class ComponentVertical : public ComponentDirection {
public:
ComponentVertical(Delegate* delegate);
bool HandleDirection(int key) override;
ComponentVertical(Delegate*);
bool HandleDirection(Event) override;
};
} // namespace component

View File

@@ -0,0 +1,35 @@
#ifndef FTXUI_COMPONENT_INPUT_H_
#define FTXUI_COMPONENT_INPUT_H_
#include "ftxui/component/component.hpp"
#include <functional>
namespace ftxui {
namespace component {
class Input : public Component {
public:
// Constructor.
Input(Delegate*);
~Input() override;
// State.
std::wstring content = L"input";
std::wstring placeholder = L"placeholder";
// State update callback.
std::function<void()> on_change = [](){};
std::function<void()> on_enter = [](){};
// Component implementation.
dom::Element Render() override;
bool OnEvent(Event) override;
private:
int cursor_position = 0;
};
} // namespace component
} // namespace ftxui
#endif /* end of include guard: FTXUI_COMPONENT_INPUT_H_ */

View File

@@ -22,7 +22,7 @@ class Menu : public Component {
// Component implementation.
dom::Element Render() override;
bool Event(int key) override;
bool OnEvent(Event) override;
};
} // namespace component

View File

@@ -22,7 +22,7 @@ class Toggle : public Component {
// Component implementation.
dom::Element Render() override;
bool Event(int key) override;
bool OnEvent(Event) override;
};
} // namespace component

View File

@@ -0,0 +1,37 @@
#ifndef FTXUI_EVENT_H_
#define FTXUI_EVENT_H_
#include <vector>
#include <array>
namespace ftxui {
struct Event{
public:
// --- Character ---
static Event Character(char);
// --- Arrow ---
static Event ArrowLeft;
static Event ArrowRight;
static Event ArrowUp;
static Event ArrowDown;
// --- Other ---
static Event Backspace;
static Event Delete;
static Event Return;
static Event Escape;
static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
bool operator==(const Event& other) { return values == other.values; }
// Internal representation.
std::array<char, 5> values = {0, 0, 0, 0, 0};
};
} // namespace ftxui
#endif /* end of include guard: FTXUI_EVENT_H_ */

View File

@@ -17,7 +17,7 @@ dom::Element Component::Render() {
return text(L"Not implemented component");
}
bool Component::Event(int key) {
bool Component::OnEvent(Event event) {
return false;
}

View File

@@ -6,17 +6,17 @@ namespace component {
ComponentDirection::ComponentDirection(Delegate* delegate)
: Component(delegate), active_child_(nullptr) {}
bool ComponentDirection::Event(int key) {
bool ComponentDirection::OnEvent(Event event) {
if (!Focused())
return false;
if (!active_child_)
return false;
if (active_child_->Event(key))
if (active_child_->OnEvent(event))
return true;
return HandleDirection(key);
return HandleDirection(event);
}
Component* ComponentDirection::GetActiveChild() {

View File

@@ -6,9 +6,9 @@ namespace component {
ComponentHorizontal::ComponentHorizontal(Delegate* delegate)
: ComponentDirection(delegate) {}
bool ComponentHorizontal::HandleDirection(int key) {
bool ComponentHorizontal::HandleDirection(Event event) {
// Left pressed ?
if (key == 68 || key == 'h') {
if (event == Event::ArrowLeft || event == Event::Character('h')) {
Component* previous_sibling = active_child_->PreviousSibling();
if (previous_sibling) {
active_child_ = previous_sibling;
@@ -17,7 +17,7 @@ bool ComponentHorizontal::HandleDirection(int key) {
}
// Left pressed ?
if (key == 67 || key == 'l') {
if (event == Event::ArrowRight || event == Event::Character('l')) {
Component* next_sibling = active_child_->NextSibling();
if (next_sibling) {
active_child_ = next_sibling;

View File

@@ -6,9 +6,9 @@ namespace component {
ComponentVertical::ComponentVertical(Delegate* delegate)
: ComponentDirection(delegate) {}
bool ComponentVertical::HandleDirection(int key) {
bool ComponentVertical::HandleDirection(Event event) {
// Up pressed ?
if (key == 65 || key == 'k') {
if (event == Event::ArrowUp || event == Event::Character('k')) {
Component* previous_sibling = active_child_->PreviousSibling();
if (previous_sibling) {
active_child_ = previous_sibling;
@@ -17,7 +17,7 @@ bool ComponentVertical::HandleDirection(int key) {
}
// Down pressed ?
if (key == 66 || key == 'j') {
if (event == Event::ArrowDown || event == Event::Character('j')) {
Component* next_sibling = active_child_->NextSibling();
if (next_sibling) {
active_child_ = next_sibling;

View File

@@ -0,0 +1,46 @@
#include "ftxui/component/input.hpp"
#include "ftxui/util/string.hpp"
namespace ftxui {
namespace component {
Input::Input(Delegate* delegate): Component(delegate) {}
Input::~Input() {}
// Component implementation.
dom::Element Input::Render() {
bool is_place_ho
std::wstring& displayed_text = content.size() ? content : placeholder;
using namespace dom;
if (Focused())
return flex(inverted(text(displayed_text)));
else
return flex(text(displayed_text));
}
bool Input::OnEvent(Event event) {
std::wstring c;
// Backspace
if (event == Event::Backspace) {
if (content.size() != 0)
content = content.substr(0, content.size()-1);
return true;
}
// Enter
if (event == Event::Return) {
return true;
}
constexpr char ESC = char(27);
if (event.values[0] != ESC) {
content += event.values[0];
return true;
}
return false;
}
} // namespace component
} // namespace ftxui

View File

@@ -1,5 +1,6 @@
#include "ftxui/component/menu.hpp"
#include <algorithm>
#include <iostream>
namespace ftxui {
namespace component {
@@ -24,14 +25,14 @@ dom::Element Menu::Render() {
return vbox(std::move(elements));
}
bool Menu::Event(int key) {
bool Menu::OnEvent(Event event) {
if (!Focused())
return false;
int new_selected = selected;
if (key == 65 || key == 'k')
if (event == Event::ArrowUp || event == Event::Character('k'))
new_selected--;
if (key == 66 || key == 'j')
if (event == Event::ArrowDown || event == Event::Character('j'))
new_selected++;
new_selected = std::max(0, std::min(int(entries.size())-1, new_selected));
@@ -41,7 +42,7 @@ bool Menu::Event(int key) {
return true;
}
if (key == 10) {
if (event == Event::Return) {
on_enter();
return true;
}

View File

@@ -24,16 +24,15 @@ dom::Element Toggle::Render() {
return hbox(std::move(children));
}
bool Toggle::Event(int key) {
bool Toggle::OnEvent(Event event) {
if (activated) {
if (key == 67 || key == 'l') {
if (event == Event::ArrowRight || event == Event::Character('l')) {
activated = false;
on_change();
return true;
}
} else {
if (key == 68 || key == 'h') {
if (event == Event::ArrowLeft || event == Event::Character('h')) {
activated = true;
on_change();
return true;

37
ftxui/src/ftxui/event.cpp Normal file
View File

@@ -0,0 +1,37 @@
#include "ftxui/event.hpp"
namespace ftxui {
constexpr char ESC = char(27);
// --- Character ---
Event Event::Character(char c) {
return Event{c};
}
// --- Arrow ---
Event Event::ArrowLeft{ESC, '[', 'D'};
Event Event::ArrowRight{ESC, '[', 'C'};
Event Event::ArrowUp{ESC, '[', 'A'};
Event Event::ArrowDown{ESC, '[', 'B'};
// --- Other ---
Event Event::Backspace{char(127)};
Event Event::Delete{ESC, '[', '3', '~'};
Event Event::Escape{ESC};
Event Event::Return{char(10)};
Event Event::F1{ESC, '[', 'O', 'P'};
Event Event::F2{ESC, '[', 'O', 'Q'};
Event Event::F3{ESC, '[', 'O', 'R'};
Event Event::F4{ESC, '[', 'O', 'S'};
Event Event::F5{ESC, '[', '1', '5', '~'};
Event Event::F6{ESC, '[', '1', '7', '~'};
Event Event::F7{ESC, '[', '1', '8', '~'};
Event Event::F8{ESC, '[', '1', '9', '~'};
Event Event::F9{ESC, '[', '2', '0', '~'};
Event Event::F10{ESC, '[', '2', '1', '~'};
Event Event::F11{ESC, '[', '2', '1', '~'}; // Same as F10 ?
Event Event::F12{ESC, '[', '2', '4', '~'};
} // namespace ftxui

View File

@@ -8,6 +8,20 @@
namespace ftxui {
namespace {
constexpr char ESC = char(27);
Event GetEvent() {
char v1 = char(getchar());
if (v1 != ESC)
return Event{v1};
char v2 = char(getchar());
char v3 = char(getchar());
return Event{v1,v2,v3};
};
};
class ScreenInteractive::Delegate : public component::Delegate {
public:
Delegate() : root_(this) {}
@@ -29,7 +43,7 @@ class ScreenInteractive::Delegate : public component::Delegate {
return child;
}
void Event(int key) { component_->Event(key); }
void OnEvent(Event event) { component_->OnEvent(event); }
std::vector<component::Delegate*> children() override {
@@ -77,8 +91,7 @@ void ScreenInteractive::Loop() {
Draw();
while (!quit_) {
int key = getchar();
delegate_->Event(key);
delegate_->OnEvent(GetEvent());
Clear();
Draw();