tap action for drawlayerproxy, text cursor for osk!

This commit is contained in:
zetaPRIME 2017-03-14 14:40:40 -04:00
parent 92467e21c6
commit 36960effa4
12 changed files with 221 additions and 17 deletions

View File

@ -100,12 +100,39 @@ OSK::OSK(osk::InputHandler* handler) : Form(true), handler(handler) {
touchScreen->Add(key); touchScreen->Add(key);
preview = std::make_shared<DrawLayerProxy>(VRect::touchScreen.TopEdge(68).Expand(-2), [this](auto& layer){ this->DrawPreview(layer); }, true); preview = std::make_shared<DrawLayerProxy>(VRect::touchScreen.TopEdge(68).Expand(-2), [this](auto& layer){ this->DrawPreview(layer); }, true);
preview->eOnTap = [this](auto& layer){ this->OnPreviewTap(layer); };
touchScreen->Add(preview); touchScreen->Add(preview);
} }
void OSK::Update(bool focused) { void OSK::Update(bool focused) {
if (focused) { if (focused) {
if (InputManager::Pressed(Keys::B)) handler->Done(); if (InputManager::Pressed(Keys::B)) handler->Done();
if (true || handler->showPreview) {
if (InputManager::Pressed(Keys::DPadLeft)) {
handler->SetCursor(handler->GetCursor() - 1);
preview->Refresh();
}
if (InputManager::Pressed(Keys::DPadRight)) {
handler->SetCursor(handler->GetCursor() + 1);
preview->Refresh();
}
static auto tc = ThemeManager::GetMetric<TextConfig>("/dialogs/OSK/preview");
if (InputManager::Pressed(Keys::DPadUp)) {
Vector2 pt = tc.font->GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor());
string msr = "|";
pt.y -= tc.font->Measure(msr).y * 0.5f;
handler->SetCursor(tc.font->GetCursorFromPoint(preview->rect, handler->GetPreviewText(), pt));
preview->Refresh();
}
if (InputManager::Pressed(Keys::DPadDown)) {
Vector2 pt = tc.font->GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor());
string msr = "|";
pt.y += tc.font->Measure(msr).y;
handler->SetCursor(tc.font->GetCursorFromPoint(preview->rect, handler->GetPreviewText(), pt));
preview->Refresh();
}
}
float& s = setContainer->scrollOffset.y; float& s = setContainer->scrollOffset.y;
float ts = 0; float ts = 0;
@ -127,5 +154,16 @@ void OSK::DrawPreview(DrawLayerProxy& layer) {
if (true || handler->showPreview) { if (true || handler->showPreview) {
static auto tc = ThemeManager::GetMetric<TextConfig>("/dialogs/OSK/preview"); static auto tc = ThemeManager::GetMetric<TextConfig>("/dialogs/OSK/preview");
tc.Print(layer.rect, handler->GetPreviewText(), Vector2::zero); tc.Print(layer.rect, handler->GetPreviewText(), Vector2::zero);
Vector2 cp = tc.font->GetCursorPosition(layer.rect, handler->GetPreviewText(), handler->GetCursor());
string cc = "|";
tc.Print(cp, cc, Vector2::zero);
} }
} }
void OSK::OnPreviewTap(DrawLayerProxy& layer) {
Vector2 tpos = InputManager::TouchPos() - layer.ScreenRect().pos;
static auto tc = ThemeManager::GetMetric<TextConfig>("/dialogs/OSK/preview");
handler->SetCursor(tc.font->GetCursorFromPoint(layer.rect, handler->GetPreviewText(), tpos + layer.rect.pos));
preview->Refresh();
}

View File

@ -28,6 +28,7 @@ namespace starlight {
void OnKey(); void OnKey();
void DrawPreview(ui::DrawLayerProxy& layer); void DrawPreview(ui::DrawLayerProxy& layer);
void OnPreviewTap(ui::DrawLayerProxy& layer);
}; };
} }
} }

View File

@ -12,17 +12,21 @@ using starlight::dialog::osk::InputHandlerBuffered;
std::string& InputHandlerDirectEdit::GetPreviewText() { return *pText; } std::string& InputHandlerDirectEdit::GetPreviewText() { return *pText; }
unsigned int InputHandlerDirectEdit::GetCursor() { return pText->length(); } unsigned int InputHandlerDirectEdit::GetCursor() { return cursor; }
void InputHandlerDirectEdit::SetCursor(unsigned int index) { } void InputHandlerDirectEdit::SetCursor(unsigned int index) { cursor = index; if (cursor < minIndex) cursor = minIndex; auto len = pText->length(); if (cursor > len) cursor = len; }
void InputHandlerDirectEdit::InputSymbol(const string& sym) { void InputHandlerDirectEdit::InputSymbol(const string& sym) {
pText->append(sym); //pText->append(sym);
pText->insert(cursor, sym);
cursor += sym.length();
if (eOnModify) eOnModify(); if (eOnModify) eOnModify();
} }
void InputHandlerDirectEdit::Backspace() { void InputHandlerDirectEdit::Backspace() {
if (pText->length() > minIndex) { if (cursor > minIndex) {
pText->pop_back(); //pText->pop_back();
pText->erase(cursor-1, 1);
cursor -= 1;
if (eOnModify) eOnModify(); if (eOnModify) eOnModify();
} }
} }

View File

@ -39,12 +39,13 @@ namespace starlight {
std::string* pText; std::string* pText;
unsigned int minIndex = 0; unsigned int minIndex = 0;
unsigned int cursor = 0;
std::function<void()> eOnModify = {}; std::function<void()> eOnModify = {};
std::function<void()> eOnFinalize = {}; std::function<void()> eOnFinalize = {};
InputHandlerDirectEdit(std::string* textptr, bool multiLine = false, unsigned int minIndex = 0, std::function<void()> onModify = {}, std::function<void()> onFinalize = {}) InputHandlerDirectEdit(std::string* textptr, bool multiLine = false, unsigned int minIndex = 0, std::function<void()> onModify = {}, std::function<void()> onFinalize = {})
: multiLine(multiLine), pText(textptr), minIndex(minIndex), eOnModify(onModify), eOnFinalize(onFinalize) { } : multiLine(multiLine), pText(textptr), minIndex(minIndex), cursor(textptr->length()), eOnModify(onModify), eOnFinalize(onFinalize) { }
~InputHandlerDirectEdit() override { } ~InputHandlerDirectEdit() override { }
std::string& GetPreviewText() override; std::string& GetPreviewText() override;

View File

@ -86,6 +86,118 @@ float BitmapFont::DrawText(const Vector2& penStart, std::string& msg, float scal
return pen.x - penStart.x; return pen.x - penStart.x;
} }
Vector2 BitmapFont::MeasureTo(std::string& msg, bool total, unsigned int end, float maxWidth) {
auto len = msg.length();
if (end > len) end = len;
Vector2 pen = Vector2::zero;
Vector2 oPen = pen;
float longest = 0;
float wordlen = 0;
float plen = 0;
float space = Char(' ').advX;
for (unsigned int i = 0; i < len; i++) {
char& c = msg[i];
if (c == ' ' || c == '\n') {
bool alb = false; // already linebreak
oPen = pen;
if (pen.x > longest) longest = pen.x;
if (pen.x + wordlen > maxWidth) {
pen.x = 0; pen.y += lineHeight;
alb = true;
}
pen.x += wordlen;
pen.x += space;
if (c == '\n' && !alb) {
if (pen.x > longest) longest = pen.x;
pen.x = 0; pen.y += lineHeight;
}
if (!total && i >= end) {
//if (c == ' ') pen.x -= space; // I think this needs to be undone too?
return Vector2(oPen.x + plen, oPen.y); // return cursor position
}
wordlen = plen = 0;
} else {
float adv = Char(c).advX;
wordlen += adv;
if (i < end) plen += adv;
}
}
{ // oh right, this check kind of needs to happen at the end too
if (pen.x > longest) longest = pen.x;
if (pen.x + wordlen > maxWidth) {
pen.x = 0; pen.y += lineHeight;
}
pen.x += wordlen;
if (!total) {
//if (c == ' ') pen.x -= space; // I think this needs to be undone too?
return Vector2(pen.x - (wordlen - plen), pen.y); // return cursor position
}
}
//if (msg.back() != '\n') pen.y += lineHeight; // trim trailing newline (todo: make this recursive...?)
pen.y += lineHeight;
return Vector2(longest, pen.y); // total size
}
unsigned int BitmapFont::PointToIndex(std::string& msg, Vector2 pt, float maxWidth) {
if (pt.y < 0) return 0;
auto len = msg.length();
unsigned int line = 0;
unsigned int tLine = std::max(0.0f, std::floor(pt.y / lineHeight));
unsigned int le = 0; // line end
unsigned int ti = 4294967295; // target index
Vector2 pen = Vector2::zero;
float wordlen = 0;
float space = Char(' ').advX;
for (unsigned int i = 0; i < len; i++) {
char& c = msg[i];
if (c == ' ' || c == '\n') {
// linebreak on newline or wrap needed
bool lb = (c == '\n' || pen.x + space + wordlen > maxWidth);
if (lb) {
if (c == '\n') le = i; // not wrapped
if (line == tLine) return std::min(le, ti);
pen.x = (c == ' ') ? wordlen : 0;
line++;
} else {
pen.x += wordlen + space;
if (line == tLine && ti == 4294967295 && pen.x - space*0.5f >= pt.x) ti = i;
le = i;
}
wordlen = 0; // HERP DERP.
} else {
float cw = Char(c).advX;
wordlen += cw;
if (line == tLine && ti == 4294967295 && pen.x + wordlen - cw*0.5f >= pt.x) ti = i;
}
}
// oh right, process last word
if (pen.x + space + wordlen > maxWidth) {
if (line == tLine) return std::min(le, ti);
pen.x = wordlen;
line++;
} else {
le = len;
}
if (line == tLine) return std::min(le, ti);
return len;
}
@ -107,10 +219,4 @@ float BitmapFont::DrawText(const Vector2& penStart, std::string& msg, float scal
//

View File

@ -49,10 +49,12 @@ namespace starlight {
CharInfo& Char(char c); CharInfo& Char(char c);
float DrawText(const Vector2& penStart, std::string& msg, float scale = 1, DisplayList* dl = nullptr); float DrawText(const Vector2& penStart, std::string& msg, float scale = 1, DisplayList* dl = nullptr);
// what to put in the bitmapfont class itself? // what to put in the bitmapfont class itself?
Vector2 MeasureTo(std::string& msg, bool total = true, unsigned int end = 4294967295, float maxWidth = 65536*64);
unsigned int PointToIndex(std::string& msg, Vector2 pt, float maxWidth = 65536*64);
static inline constexpr unsigned int KerningKey(char cl, char cr) { static inline constexpr unsigned int KerningKey(char cl, char cr) {
return (static_cast<unsigned int>(cl) | (static_cast<unsigned int>(cr) << 8)); return (static_cast<unsigned int>(cl) | (static_cast<unsigned int>(cr) << 8));
} }
}; };
} }
} }

View File

@ -24,6 +24,9 @@ namespace starlight {
virtual void Print(VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0; virtual void Print(VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
virtual void PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0; virtual void PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
virtual void PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0; virtual void PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) = 0;
virtual Vector2 GetCursorPosition(VRect rect, std::string& text, unsigned int end, float scale = 1) = 0;
virtual unsigned int GetCursorFromPoint(VRect rect, std::string& text, Vector2 pt, float scale = 1) = 0;
}; };
} }

View File

@ -18,9 +18,10 @@ using starlight::gfx::FontBMF;
#define ded(wat) err(0,wat) #define ded(wat) err(0,wat)
Vector2 FontBMF::Measure(std::string& text, float scale, float maxWidth) { Vector2 FontBMF::Measure(std::string& text, float scale, float maxWidth) {
if (text == "") return Vector2::zero; if (text == "") return Vector2::zero;
Vector2 v; /*Vector2 v;
PrintOp(Vector2(), text, scale, Color(), Vector2(), nullptr, maxWidth, &v, static_cast<DisplayList*>(nullptr)); PrintOp(Vector2(), text, scale, Color(), Vector2(), nullptr, maxWidth, &v, static_cast<DisplayList*>(nullptr));
return v; return v;*/
return font->MeasureTo(text, true, text.length(), maxWidth) * scale;
} }
void FontBMF::Print(Vector2 position, std::string& text, float scale, Color color, Vector2 justification, OptRef<Color> borderColor) { void FontBMF::Print(Vector2 position, std::string& text, float scale, Color color, Vector2 justification, OptRef<Color> borderColor) {
@ -139,3 +140,11 @@ void FontBMF::PrintOp(Vector2 position, std::string& text, float scale, const Co
li++; li++;
} }
} }
Vector2 FontBMF::GetCursorPosition(VRect rect, std::string& text, unsigned int end, float scale) {
return rect.pos + (font->MeasureTo(text, false, end, rect.size.x / scale)* scale);
}
unsigned int FontBMF::GetCursorFromPoint(VRect rect, std::string& text, Vector2 pt, float scale) {
return font->PointToIndex(text, pt*scale - rect.pos, rect.size.x / scale);
}

View File

@ -23,6 +23,9 @@ namespace starlight {
void Print(VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override; void Print(VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
void PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override; void PrintDisplayList(DisplayList* dl, Vector2 position, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
void PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override; void PrintDisplayList(DisplayList* dl, VRect rect, std::string& text, float scale = 1, Color color = Color::white, Vector2 justification = Vector2::zero, OptRef<Color> borderColor = nullptr) override;
Vector2 GetCursorPosition(VRect rect, std::string& text, unsigned int end, float scale) override;
unsigned int GetCursorFromPoint(VRect rect, std::string& text, Vector2 pt, float scale) override;
}; };
} }
} }

View File

@ -1,10 +1,13 @@
#include "DrawLayerProxy.h" #include "DrawLayerProxy.h"
#include "starlight/GFXManager.h" #include "starlight/GFXManager.h"
#include "starlight/InputManager.h"
using starlight::GFXManager; using starlight::GFXManager;
using starlight::gfx::DrawContextCanvas; using starlight::gfx::DrawContextCanvas;
using starlight::InputManager;
using starlight::ui::DrawLayerProxy; using starlight::ui::DrawLayerProxy;
void DrawLayerProxy::Refresh() { void DrawLayerProxy::Refresh() {
@ -31,3 +34,29 @@ void DrawLayerProxy::Draw() {
if (eDraw) eDraw(*this); if (eDraw) eDraw(*this);
} }
} }
void DrawLayerProxy::OnTouchOn() {
if (!eOnTap) return;
if (InputManager::Pressed(Keys::Touch)) {
InputManager::GetDragHandle().Grab(this);
MarkForRedraw();
}
}
void DrawLayerProxy::OnTouchOff() {
auto& drag = InputManager::GetDragHandle();
if (drag == this) drag.Release();
}
void DrawLayerProxy::OnDragHold() {
if (InputManager::TouchDragDist().Length() > InputManager::dragThreshold) {
InputManager::GetDragHandle().PassUp();
}
}
void DrawLayerProxy::OnDragRelease() {
if (InputManager::Released(Keys::Touch)) {
if (eOnTap) eOnTap(*this);
}
MarkForRedraw();
}

View File

@ -24,6 +24,7 @@ namespace starlight {
std::unique_ptr<gfx::DrawContextCanvas> canvas; std::unique_ptr<gfx::DrawContextCanvas> canvas;
std::function<void(DrawLayerProxy&)> eDraw; std::function<void(DrawLayerProxy&)> eDraw;
std::function<void(DrawLayerProxy&)> eOnTap;
DrawLayerProxy(VRect rect, std::function<void(DrawLayerProxy&)> drawFunc, bool useCanvas = false) : useCanvas(useCanvas), eDraw(drawFunc) { this->rect = rect; } DrawLayerProxy(VRect rect, std::function<void(DrawLayerProxy&)> drawFunc, bool useCanvas = false) : useCanvas(useCanvas), eDraw(drawFunc) { this->rect = rect; }
~DrawLayerProxy() override { } ~DrawLayerProxy() override { }
@ -34,6 +35,11 @@ namespace starlight {
void PreDraw() override; void PreDraw() override;
void Draw() override; void Draw() override;
void OnTouchOn() override;
void OnTouchOff() override;
void OnDragHold() override;
void OnDragRelease() override;
// //
}; };
} }

View File

@ -6,7 +6,9 @@ roadmap to first release, in no particular order {
finish implementing OSK! { finish implementing OSK! {
- make backspace and enter actually do something - make backspace and enter actually do something
- abstract osk input actions into a separate object/class heirarchy - abstract osk input actions into a separate object/class heirarchy
preview where applicable - preview where applicable
fix desync between cursor position, tap-cursor and display when a single word overflows a line
(cursor doesn't wrap until the next word!?)
polish! polish!
InputManager::OpenKeyboard InputManager::OpenKeyboard
} }