add OSK preview scrolling, background, fix DrawLayerProxy,

make TextConfig.Print string ref const, make form priority float,
ScrollField::ScrollIntoView, minor BitmapFont fix
This commit is contained in:
zetaPRIME 2017-03-16 20:35:04 -04:00
parent 5d7fd4d802
commit 5954dc5768
15 changed files with 98 additions and 35 deletions

View File

@ -347,11 +347,11 @@ TextConfig::TextConfig(const std::string& fontName, Color text, Color border) {
textColor = text; borderColor = border; textColor = text; borderColor = border;
} }
void TextConfig::Print(Vector2 position, std::string& text, Vector2 justification) { void TextConfig::Print(Vector2 position, const std::string& text, Vector2 justification) {
if (!justification) justification = this->justification; if (!justification) justification = this->justification;
font->Print(position, text, 1, textColor, justification, borderColor); font->Print(position, text, 1, textColor, justification, borderColor);
} }
void TextConfig::Print(VRect rect, std::string& text, Vector2 justification) { void TextConfig::Print(VRect rect, const std::string& text, Vector2 justification) {
if (!justification) justification = this->justification; if (!justification) justification = this->justification;
font->Print(rect, text, 1, textColor, justification, borderColor); font->Print(rect, text, 1, textColor, justification, borderColor);
} }

View File

@ -85,8 +85,8 @@ namespace starlight {
TextConfig(const std::string& fontName, Color text, Color border = Color::transparent); TextConfig(const std::string& fontName, Color text, Color border = Color::transparent);
~TextConfig() = default; ~TextConfig() = default;
void Print(Vector2 position, std::string& text, Vector2 justification = Vector2::invalid); void Print(Vector2 position, const std::string& text, Vector2 justification = Vector2::invalid);
void Print(VRect rect, std::string& text, Vector2 justification = Vector2::invalid); void Print(VRect rect, const std::string& text, Vector2 justification = Vector2::invalid);
Vector2 Measure(const std::string& text, float maxWidth = 65536*64); Vector2 Measure(const std::string& text, float maxWidth = 65536*64);

View File

@ -32,7 +32,7 @@ namespace starlight {
VRect Intersect(const VRect & o) const; VRect Intersect(const VRect & o) const;
VRect Expand(const Vector2& amount, const Vector2& bias) const; VRect Expand(const Vector2& amount, const Vector2& bias) const;
VRect Expand(const Vector2& amount) const { return Expand(amount, Vector2::half); } VRect Expand(const Vector2& amount) const { return Expand(amount, Vector2::half); }
VRect Expand(float x, float y) const { return Expand(Vector2(x, y )); } VRect Expand(float x, float y) const { return Expand(Vector2(x, y)); }
VRect Include(const Vector2& point) const; VRect Include(const Vector2& point) const;

View File

@ -36,13 +36,15 @@ namespace {
static auto tc = ThemeManager::GetMetric<starlight::TextConfig>("/dialogs/OSK/preview"); static auto tc = ThemeManager::GetMetric<starlight::TextConfig>("/dialogs/OSK/preview");
return tc; return tc;
} }
const constexpr float textHang = 4;
} }
OSK::OSK(osk::InputHandler* handler) : Form(true), handler(handler) { OSK::OSK(osk::InputHandler* handler) : Form(true), handler(handler) {
priority = 1000; // probably don't want all that much displaying above the keyboard priority = 1000; // probably don't want all that much displaying above the keyboard
handler->parent = this; handler->parent = this;
auto cover = std::make_shared<Image>(touchScreen->rect.Expand(4), "decorations/dialog.modal-cover"); auto cover = std::make_shared<Image>(touchScreen->rect, "decorations/osk.background");
cover->blockTouch = true; cover->blockTouch = true;
touchScreen->Add(cover); touchScreen->Add(cover);
@ -58,7 +60,7 @@ OSK::OSK(osk::InputHandler* handler) : Form(true), handler(handler) {
Vector2 bs(24, 32); Vector2 bs(24, 32);
Vector2 bpen; Vector2 bpen;
Vector2 bpstart(160-bs.x*(12.5/2), 68); Vector2 bpstart(160-bs.x*(12.5/2), 68+5);
int line = -1; int line = -1;
float linestart [] = {0, .5, .75, 1.25, 2.75-1}; float linestart [] = {0, .5, .75, 1.25, 2.75-1};
string chr = "\n1234567890-=\nqwertyuiop[]\nasdfghjkl;\'\nzxcvbnm,./\n` \\"; string chr = "\n1234567890-=\nqwertyuiop[]\nasdfghjkl;\'\nzxcvbnm,./\n` \\";
@ -106,9 +108,14 @@ OSK::OSK(osk::InputHandler* handler) : Form(true), handler(handler) {
key->eOnTap = [this](auto& btn){ this->handler->Enter(); this->OnKey(); }; key->eOnTap = [this](auto& btn){ this->handler->Enter(); this->OnKey(); };
touchScreen->Add(key); touchScreen->Add(key);
preview = std::make_shared<DrawLayerProxy>(VRect::touchScreen.TopEdge(68).Expand(-2), [this](auto& layer){ this->DrawPreview(layer); }, true); previewSc = std::make_shared<ScrollField>(VRect(VRect::touchScreen.TopEdge(66)));
touchScreen->Add(previewSc);
preview = std::make_shared<DrawLayerProxy>(VRect::touchScreen.TopEdge(66).Expand(-2, 0), [this](auto& layer){ this->DrawPreview(layer); }, true);
preview->eOnTap = [this](auto& layer){ this->OnPreviewTap(layer); }; preview->eOnTap = [this](auto& layer){ this->OnPreviewTap(layer); };
touchScreen->Add(preview); previewSc->Add(preview);
RefreshPreview();
} }
void OSK::Update(bool focused) { void OSK::Update(bool focused) {
@ -117,30 +124,29 @@ 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 (handler->showPreview) {
if (InputManager::Pressed(Keys::DPadLeft)) { if (InputManager::Pressed(Keys::DPadLeft)) {
handler->SetCursor(handler->GetCursor() - 1); auto c = handler->GetCursor();
preview->Refresh(); if (c > 0) handler->SetCursor(c - 1);
RefreshPreview();
} }
if (InputManager::Pressed(Keys::DPadRight)) { if (InputManager::Pressed(Keys::DPadRight)) {
handler->SetCursor(handler->GetCursor() + 1); handler->SetCursor(handler->GetCursor() + 1);
preview->Refresh(); RefreshPreview();
} }
auto& tc = PreviewTC(); auto& tc = PreviewTC();
if (InputManager::Pressed(Keys::DPadUp)) { if (InputManager::Pressed(Keys::DPadUp)) {
Vector2 pt = tc.GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor()); Vector2 pt = tc.GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor());
string msr = "|"; pt.y -= tc.Measure("|").y * 0.5f;
pt.y -= tc.Measure(msr).y * 0.5f;
handler->SetCursor(tc.GetCursorFromPoint(preview->rect, handler->GetPreviewText(), pt)); handler->SetCursor(tc.GetCursorFromPoint(preview->rect, handler->GetPreviewText(), pt));
preview->Refresh(); RefreshPreview();
} }
if (InputManager::Pressed(Keys::DPadDown)) { if (InputManager::Pressed(Keys::DPadDown)) {
Vector2 pt = tc.GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor()); Vector2 pt = tc.GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor());
string msr = "|"; pt.y += tc.Measure("|").y * 1.5f;
pt.y += tc.Measure(msr).y * 1.5f;
handler->SetCursor(tc.GetCursorFromPoint(preview->rect, handler->GetPreviewText(), pt)); handler->SetCursor(tc.GetCursorFromPoint(preview->rect, handler->GetPreviewText(), pt));
preview->Refresh(); RefreshPreview();
} }
} }
@ -157,23 +163,47 @@ void OSK::Update(bool focused) {
} }
void OSK::OnKey() { void OSK::OnKey() {
RefreshPreview();
}
void OSK::RefreshPreview() {
auto& tc = PreviewTC();
if (handler->showPreview) {
Vector2 sz = tc.Measure(handler->GetPreviewText(), preview->rect.size.x);
preview->Resize(Vector2(preview->rect.size.x, std::max(sz.y + textHang, previewSc->rect.size.y))); // I guess a magic four will do
Vector2 cp = tc.GetCursorPosition(preview->rect, handler->GetPreviewText(), handler->GetCursor());
Vector2 cs = tc.Measure("|") + Vector2(0, textHang);
previewSc->ScrollIntoView(VRect(cp, cs));//*/
} else {
preview->Resize(Vector2(preview->rect.size.x, 66));
}
preview->Refresh(); preview->Refresh();
} }
void OSK::DrawPreview(DrawLayerProxy& layer) { void OSK::DrawPreview(DrawLayerProxy& layer) {
if (true || handler->showPreview) { if (handler->showPreview) {
auto& tc = PreviewTC(); auto& tc = PreviewTC();
tc.Print(layer.rect, handler->GetPreviewText(), Vector2::zero); tc.Print(layer.rect, handler->GetPreviewText(), Vector2::zero);
Vector2 cp = tc.GetCursorPosition(layer.rect, handler->GetPreviewText(), handler->GetCursor()); Vector2 cp = tc.GetCursorPosition(layer.rect, handler->GetPreviewText(), handler->GetCursor());
string cc = "|"; string cc = "|";
tc.Print(cp, cc, Vector2::zero); tc.Print(cp, cc);
//Vector2 cs = tc.Measure("|") + Vector2(0, textHang);
//previewSc->ScrollIntoView(VRect(cp, cs));
} else {
static auto tc = ThemeManager::GetMetric<starlight::TextConfig>("/dialogs/OSK/noPreview");
tc.Print(layer.rect, "(no preview available)");
} }
} }
void OSK::OnPreviewTap(DrawLayerProxy& layer) { void OSK::OnPreviewTap(DrawLayerProxy& layer) {
Vector2 tpos = InputManager::TouchPos() - layer.ScreenRect().pos; if (handler->showPreview) {
auto& tc = PreviewTC(); Vector2 tpos = InputManager::TouchPos() - layer.ScreenRect().pos;
handler->SetCursor(tc.GetCursorFromPoint(layer.rect, handler->GetPreviewText(), tpos)); auto& tc = PreviewTC();
preview->Refresh(); handler->SetCursor(tc.GetCursorFromPoint(layer.rect, handler->GetPreviewText(), tpos));
RefreshPreview();
}
} }

View File

@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include "starlight/ui/Form.h" #include "starlight/ui/Form.h"
#include "starlight/ui/ScrollField.h"
#include "starlight/ui/DrawLayerProxy.h" #include "starlight/ui/DrawLayerProxy.h"
#include "starlight/dialog/osk/InputHandler.h" #include "starlight/dialog/osk/InputHandler.h"
@ -15,7 +16,10 @@ namespace starlight {
class OSK : public ui::Form, public ui::FormCreator<OSK> { class OSK : public ui::Form, public ui::FormCreator<OSK> {
private: private:
std::shared_ptr<ui::UIContainer> setContainer; std::shared_ptr<ui::UIContainer> setContainer;
std::shared_ptr<ui::ScrollField> previewSc;
std::shared_ptr<ui::DrawLayerProxy> preview; std::shared_ptr<ui::DrawLayerProxy> preview;
//Vector2 cursorPos;
public: public:
std::unique_ptr<osk::InputHandler> handler; std::unique_ptr<osk::InputHandler> handler;
@ -27,6 +31,7 @@ namespace starlight {
void OnKey(); void OnKey();
void RefreshPreview();
void DrawPreview(ui::DrawLayerProxy& layer); void DrawPreview(ui::DrawLayerProxy& layer);
void OnPreviewTap(ui::DrawLayerProxy& layer); void OnPreviewTap(ui::DrawLayerProxy& layer);
}; };

View File

@ -64,7 +64,9 @@ BitmapFont::CharInfo& BitmapFont::Char(char c) {
} }
Vector2 BitmapFont::MeasureTo(const std::string& msg, bool total, unsigned int end, float maxWidth) { Vector2 BitmapFont::MeasureTo(const std::string& msg, bool total, unsigned int end, float maxWidth) {
if (msg == "") return Vector2::zero;
if (total) { if (total) {
if (end == 0) return Vector2(0, lineHeight);
Vector2 measure = Vector2::zero; Vector2 measure = Vector2::zero;
ForChar(msg, [&, this](auto& s){ ForChar(msg, [&, this](auto& s){
@ -81,11 +83,14 @@ Vector2 BitmapFont::MeasureTo(const std::string& msg, bool total, unsigned int e
Vector2 measure; Vector2 measure;
bool found = false; bool found = false;
ForChar(msg, [&, this, total, end](auto& s){ unsigned int et = end - 1;
if (end == 0) et = 0;
ForChar(msg, [&, this, total, end, et](auto& s){
measure = Vector2(s.lineAcc + s.cc->advX, lineHeight * s.lineNum); measure = Vector2(s.lineAcc + s.cc->advX, lineHeight * s.lineNum);
if (s.i == end-1) { if (s.i >= et) {
found = true; found = true;
if (s.i == s.lineEnd) measure = Vector2(0, lineHeight * (s.lineNum + 1)); // linebreak == next line if (s.i == s.lineEnd) measure = Vector2(0, lineHeight * (s.lineNum + 1)); // linebreak == next line
if (end == 0) measure = Vector2(0, lineHeight * s.lineNum);
return true; return true;
} }

View File

@ -29,6 +29,7 @@ void DrawLayerProxy::PreDraw() {
void DrawLayerProxy::Draw() { void DrawLayerProxy::Draw() {
if (canvas) { if (canvas) {
auto rect = (this->rect + GFXManager::GetOffset()).IntSnap();
canvas->Draw(VRect(rect.pos, canvas->rect.size)); canvas->Draw(VRect(rect.pos, canvas->rect.size));
} else { } else {
if (eDraw) eDraw(*this); if (eDraw) eDraw(*this);

View File

@ -58,7 +58,7 @@ namespace starlight {
// //
public: public:
int priority = 0; float priority = 0;
unsigned int flags = 0; unsigned int flags = 0;
std::shared_ptr<UIContainer> touchScreen = nullptr; std::shared_ptr<UIContainer> touchScreen = nullptr;

View File

@ -38,6 +38,18 @@ void ScrollField::Update() {
scrollOffset.y = std::max(0.0f, std::min(scrollOffset.y, scrollMax.y)); scrollOffset.y = std::max(0.0f, std::min(scrollOffset.y, scrollMax.y));
} }
void ScrollField::ScrollIntoView(Vector2 pt) {
Vector2 sm = pt - rect.size;
scrollOffset.x = std::max(sm.x, std::min(scrollOffset.x, pt.x));
scrollOffset.y = std::max(sm.y, std::min(scrollOffset.y, pt.y));
// hmm. doesn't play well with pending resizes
//scrollOffset.x = std::max(0.0f, std::min(scrollOffset.x, scrollMax.x));
//scrollOffset.y = std::max(0.0f, std::min(scrollOffset.y, scrollMax.y));
}
void ScrollField::ScrollIntoView(VRect box) { ScrollIntoView(box.BottomRight()); ScrollIntoView(box.pos); }
void ScrollField::OnProcessTouchEvent() { // stop when child element touched void ScrollField::OnProcessTouchEvent() { // stop when child element touched
if (InputManager::Pressed(Keys::Touch)) scrollVel = Vector2::zero; if (InputManager::Pressed(Keys::Touch)) scrollVel = Vector2::zero;
} }

View File

@ -16,6 +16,9 @@ namespace starlight {
void Update() override; void Update() override;
void ScrollIntoView(Vector2 pt);
void ScrollIntoView(VRect box);
// events // events
void OnTouchOn() override; void OnTouchOn() override;
void OnTouchOff() override { } void OnTouchOff() override { }
@ -33,4 +36,3 @@ namespace starlight {
}; };
} }
} }

View File

@ -3,20 +3,21 @@
roadmap to first release, in no particular order { roadmap to first release, in no particular order {
finish implementing OSK! { finish implementing OSK! {
enable scrolling preview (and scroll to cursor where applicable) - fix cursor-down
polish! polish! {
- background
actual cursor image?
}
InputManager::OpenKeyboard InputManager::OpenKeyboard
} }
fix [ offset (-1 it)
add generic backdrop assets (and form) add generic backdrop assets (and form)
fix lowercase j running into things
adjust monospace line height (and maybe offset) to closer match the vwf of the same size
add license!! (MIT?) add license!! (MIT?)
ADD README.MD PLS ADD README.MD PLS
} then consider these before 1.0 "gold" { } then consider these before 1.0 "gold" {
should form priority be a float? - should form priority be a float?
make closing forms a bit less finicky (add them to a separate list and let the Application remove them from the list) make closing forms a bit less finicky (add them to a separate list and let the Application remove them from the list)
add customization for Button (alternate idle/press images, optional glyph drawable) add customization for Button (alternate idle/press images, optional glyph drawable)
^ use that to spice up the OSK ^ use that to spice up the OSK

View File

@ -78,6 +78,7 @@ void Core::Init() {
auto tb = std::make_shared<sl::ui::TextBox>(VRect(0, 64, 320, 24).Expand(-16, 0)); auto tb = std::make_shared<sl::ui::TextBox>(VRect(0, 64, 320, 24).Expand(-16, 0));
tb->text = "TextBox testing in progress. ij ji lj jl"; tb->text = "TextBox testing in progress. ij ji lj jl";
tb->multiLine = true;
form->touchScreen->Add(tb); form->touchScreen->Add(tb);
/*label->SetFont("default.16"); /*label->SetFont("default.16");

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

View File

@ -45,6 +45,12 @@
"font" : "default.16", "font" : "default.16",
"textColor" : "white", "textColor" : "white",
"borderColor" : "black" "borderColor" : "black"
},
"noPreview" : {
"font" : "default.16",
"textColor" : "midGray",
"borderColor" : "darkGray",
"justification" : [0.5, 0.5]
} }
} }
}, },