forked from Mirror/libstarlight
partially-implemented OSK! more metrics implementation,
a few constants, Image::blockTouch and modal cover
This commit is contained in:
parent
01580c8dda
commit
abc3eac3e1
@ -140,7 +140,7 @@ ThemeInfo::ThemeInfo(const Path& path, const std::string& name) {
|
||||
basePath = path;
|
||||
meta = std::make_shared<nlohmann::json>();
|
||||
metrics = std::make_shared<nlohmann::json>();
|
||||
if (!basePath.IsDirectory()) return; // don't bother trying to load stuff
|
||||
//if (!basePath.IsDirectory() && std::string(basePath).find("romfs:") != std::string::npos) return; // don't bother trying to load stuff
|
||||
{ // using...
|
||||
std::ifstream load = basePath.Combine("meta.json").OpenI();
|
||||
if (load.good()) load >> *meta;
|
||||
@ -163,6 +163,7 @@ void ThemeManager::Init() {
|
||||
if (!thm.basePath.IsDirectory()) thm = ThemeInfo("default"); // fall back on default if not found
|
||||
// ...and if "default" doesn't exist, fall back on a standard location in romfs:
|
||||
if (!thm.basePath.IsDirectory()) thm = ThemeInfo(Path("romfs:/.fallback_theme", "FALLBACK"));
|
||||
if (!thm.basePath.IsDirectory()) thm = ThemeInfo(Path("romfs:/", "FALLBACK")); // fall back on root of romfs for testbed I guess
|
||||
themeData.push_back(thm);
|
||||
|
||||
while (!(*thm.meta)["fallback"].is_null()) { // follow fallback chain
|
||||
@ -319,6 +320,13 @@ T ThemeManager::GetMetric(const std::string& path, const T& defaultValue) {
|
||||
}//*/
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T ThemeManager::GetMetric(const std::string& path) {
|
||||
json& j = GetMetric(path);
|
||||
if (j.is_null()) return T();
|
||||
return j;
|
||||
}
|
||||
|
||||
TextConfig::TextConfig(const std::string& fontName, Color text, Color border) {
|
||||
font = ThemeManager::GetFont(fontName);
|
||||
textColor = text; borderColor = border;
|
||||
@ -343,8 +351,13 @@ namespace starlight { // todo: expose these in the header
|
||||
}
|
||||
}
|
||||
|
||||
template Vector2 ThemeManager::GetMetric(const std::string&, const Vector2&);
|
||||
template VRect ThemeManager::GetMetric(const std::string&, const VRect&);
|
||||
template Color ThemeManager::GetMetric(const std::string&, const Color&);
|
||||
// explicit type conversions for metrics
|
||||
#define typeconv(t) \
|
||||
template t ThemeManager::GetMetric(const std::string&, const t &); \
|
||||
template t ThemeManager::GetMetric(const std::string&);
|
||||
|
||||
template starlight::TextConfig ThemeManager::GetMetric(const std::string&, const TextConfig&);
|
||||
typeconv(Vector2);
|
||||
typeconv(VRect);
|
||||
typeconv(Color);
|
||||
|
||||
typeconv(TextConfig);
|
||||
|
@ -66,6 +66,7 @@ namespace starlight {
|
||||
static inline std::string GetThemeName() { return themeData.front().name; }
|
||||
static nlohmann::json& GetMetric(const std::string& path);
|
||||
template <typename T> static T GetMetric(const std::string& path, const T& defaultValue);
|
||||
template <typename T> static T GetMetric(const std::string& path);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -58,3 +58,6 @@ VRect VRect::RightEdge(float width) const { return VRect(pos.x + size.x - widt
|
||||
const VRect VRect::invalid = VRect(Vector2::invalid, Vector2::invalid);
|
||||
|
||||
const VRect VRect::zero = VRect(); // should initialize to 0,0,0,0
|
||||
|
||||
const VRect VRect::touchScreen = VRect(0, 0, 320, 240);
|
||||
const VRect VRect::topScreen = VRect(0, 0, 400, 240);
|
||||
|
@ -58,5 +58,8 @@ namespace starlight {
|
||||
|
||||
static const VRect invalid;
|
||||
static const VRect zero;
|
||||
|
||||
static const VRect touchScreen;
|
||||
static const VRect topScreen;
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "MessageBox.h"
|
||||
|
||||
#include "starlight/ThemeManager.h"
|
||||
#include "starlight/InputManager.h"
|
||||
|
||||
#include "starlight/ui/Image.h"
|
||||
@ -22,7 +23,11 @@ MessageBox::MessageBox(Mode m, const std::string& msg, std::function<void(int)>
|
||||
priority = 10;
|
||||
eOnSelect = onSelect;
|
||||
|
||||
VRect boxArea = VRect(160, 120, 0, 0).Expand(Vector2(240, 160)*.5);
|
||||
VRect boxArea = VRect(160, 120, 0, 0).Expand(ThemeManager::GetMetric<Vector2>("/dialogs/messageBox/size")*.5);
|
||||
|
||||
auto cover = std::make_shared<Image>(touchScreen->rect.Expand(4), "decorations/dialog.modal-cover");
|
||||
cover->blockTouch = true;
|
||||
touchScreen->Add(cover);
|
||||
|
||||
auto bg = std::make_shared<Image>(boxArea, "decorations/panel.bg");
|
||||
touchScreen->Add(bg);
|
||||
@ -30,7 +35,7 @@ MessageBox::MessageBox(Mode m, const std::string& msg, std::function<void(int)>
|
||||
touchScreen->Add(scroll);
|
||||
auto label = std::make_shared<Label>(VRect(0, 0, scroll->rect.size.x, 0));
|
||||
label->autoSizeV = true;
|
||||
label->SetFont("default.16");
|
||||
label->SetPreset("normal.16");
|
||||
label->SetText(msg);
|
||||
scroll->Add(label);
|
||||
|
||||
|
116
libstarlight/source/starlight/dialog/OSK.cpp
Normal file
116
libstarlight/source/starlight/dialog/OSK.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "OSK.h"
|
||||
|
||||
#include "starlight/ThemeManager.h"
|
||||
#include "starlight/InputManager.h"
|
||||
|
||||
#include "starlight/ui/Image.h"
|
||||
#include "starlight/ui/Button.h"
|
||||
#include "starlight/ui/Label.h"
|
||||
#include "starlight/ui/ScrollField.h"
|
||||
|
||||
#include "starlight/ConfigManager.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
using starlight::InputManager;
|
||||
|
||||
using starlight::ui::Image;
|
||||
using starlight::ui::Button;
|
||||
using starlight::ui::Label;
|
||||
using starlight::ui::ScrollField;
|
||||
|
||||
using starlight::ui::Form;
|
||||
|
||||
using starlight::dialog::OSK;
|
||||
|
||||
OSK::OSK(std::string* textptr, std::function<void()> onModify) : Form(true) {
|
||||
priority = 1000; // probably don't want all that much displaying above the keyboard
|
||||
eOnModify = onModify;
|
||||
pText = textptr;
|
||||
|
||||
auto cover = std::make_shared<Image>(touchScreen->rect.Expand(4), "decorations/dialog.modal-cover");
|
||||
cover->blockTouch = true;
|
||||
touchScreen->Add(cover);
|
||||
|
||||
// wip
|
||||
|
||||
setContainer = std::make_shared<ui::UIContainer>(VRect::touchScreen);
|
||||
touchScreen->Add(setContainer);
|
||||
|
||||
auto actSym = [this](Button& key){
|
||||
this->OnSymKey(key.label);
|
||||
};
|
||||
|
||||
Vector2 bs(24, 32);
|
||||
Vector2 bpen;
|
||||
Vector2 bpstart(160-bs.x*(12.5/2), 68);
|
||||
int line = -1;
|
||||
float linestart [] = {0, .5, .75, 1.25, 2.75-1};
|
||||
string chr = "\n1234567890-=\nqwertyuiop[]\nasdfghjkl;\'\nzxcvbnm,./\n` \\";
|
||||
string Chr = "\n!@#$%^&*()_+\nQWERTYUIOP{}\nASDFGHJKL:\"\nZXCVBNM<>?\n~ |";
|
||||
|
||||
for (unsigned int ic = 0; ic < chr.length(); ic++) {
|
||||
char& c = chr[ic];
|
||||
char& C = Chr[ic];
|
||||
if (c == '\n') {
|
||||
line++;
|
||||
bpen = bpstart + Vector2(linestart[line] * bs.x, bs.y * line);
|
||||
} else {
|
||||
// lower
|
||||
auto key = std::make_shared<Button>(VRect(bpen, bs));
|
||||
if (c == ' ') key->rect.size.x *= 6;
|
||||
key->SetText(string(1, c));
|
||||
key->eOnTap = actSym;
|
||||
setContainer->Add(key);
|
||||
|
||||
// upper
|
||||
key = std::make_shared<Button>(VRect(bpen + Vector2(0, 1000), bs));
|
||||
if (C == ' ') key->rect.size.x *= 6;
|
||||
key->SetText(string(1, C));
|
||||
key->eOnTap = actSym;
|
||||
setContainer->Add(key);
|
||||
|
||||
// and after
|
||||
bpen.x += key->rect.size.x;
|
||||
}
|
||||
}
|
||||
|
||||
// backspace
|
||||
bpen = bpstart + bs * Vector2(linestart[3] + 10, 3);
|
||||
auto key = std::make_shared<Button>(VRect(bpen, bs));
|
||||
key->rect.size.x *= 1.25;
|
||||
key->SetText("< <");
|
||||
touchScreen->Add(key);
|
||||
|
||||
bpen = bpstart + bs * Vector2(linestart[4] + 8, 4);
|
||||
key = std::make_shared<Button>(VRect(bpen, bs));
|
||||
key->rect.size.x *= 2.5;
|
||||
key->SetText("Enter");
|
||||
touchScreen->Add(key);
|
||||
|
||||
}
|
||||
|
||||
void OSK::Update(bool focused) {
|
||||
if (focused) {
|
||||
if (InputManager::Pressed(Keys::B)) Close();
|
||||
|
||||
float& s = setContainer->scrollOffset.y;
|
||||
float ts = 0;
|
||||
if (InputManager::Held(Keys::L) || InputManager::Held(Keys::R)) {
|
||||
ts = 1000;
|
||||
}
|
||||
if (s != ts) {
|
||||
s = ts;
|
||||
setContainer->MarkForRedraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OSK::OnSymKey(const string& chr) {
|
||||
pText->append(chr);
|
||||
//pText->append("sackboy ");
|
||||
//auto& tx = *pText;
|
||||
//ConfigManager::Get("user").Json()["log"].push_back(*pText);
|
||||
//tx.assign("shickaxe");
|
||||
if (eOnModify) eOnModify();
|
||||
}
|
28
libstarlight/source/starlight/dialog/OSK.h
Normal file
28
libstarlight/source/starlight/dialog/OSK.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include "starlight/_global.h"
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include "starlight/ui/Form.h"
|
||||
|
||||
namespace starlight {
|
||||
namespace dialog {
|
||||
class OSK : public ui::Form, public ui::FormCreator<OSK> {
|
||||
private:
|
||||
std::shared_ptr<ui::UIContainer> setContainer;
|
||||
|
||||
public:
|
||||
std::string* pText = nullptr;
|
||||
|
||||
std::function<void()> eOnModify;
|
||||
|
||||
OSK(std::string* textptr, std::function<void()> onModify = {});
|
||||
~OSK() override { };
|
||||
|
||||
void Update(bool focused) override;
|
||||
|
||||
void OnSymKey(const std::string& chr);
|
||||
};
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ void Button::Draw() {
|
||||
}
|
||||
|
||||
//font->Print(rect, label, 1, cl/*Color::white*/, Vector2(0.5f, 0.5f), Color::black);
|
||||
tc.Print(rect, label, Vector2(0.5f, 0.5f));
|
||||
tc.Print(rect, label, Vector2::half);
|
||||
}
|
||||
|
||||
void Button::OnTouchOn() {
|
||||
|
@ -19,6 +19,7 @@ namespace starlight {
|
||||
public:
|
||||
gfx::ThemeRef<gfx::Drawable> image;
|
||||
Color tint = Color::white;
|
||||
bool blockTouch = false;
|
||||
|
||||
Image(VRect rect, const std::string& imgPath);
|
||||
Image(Vector2 pos, const std::string& imgPath);
|
||||
@ -27,6 +28,8 @@ namespace starlight {
|
||||
void SetImage(const std::string& imgPath, bool resize = true);
|
||||
|
||||
void Draw() override;
|
||||
|
||||
bool InterceptsTouch(Vector2 where) override { return blockTouch; }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ using starlight::ui::Label;
|
||||
|
||||
Label::Label(VRect rect) {
|
||||
this->rect = rect;
|
||||
font = ThemeManager::GetFont("default.12");
|
||||
textConfig = ThemeManager::GetMetric<TextConfig>("/textPresets/normal.12", TextConfig());
|
||||
}
|
||||
|
||||
void Label::AutoSize() {
|
||||
if (autoSizeV) {
|
||||
float h = font->Measure(text, 1, rect.size.x).y;
|
||||
float h = textConfig.font->Measure(text, 1, rect.size.x).y;
|
||||
Resize(rect.size.x, h);
|
||||
}
|
||||
|
||||
@ -28,10 +28,17 @@ void Label::SetText(const std::string& text) {
|
||||
}
|
||||
|
||||
void Label::SetFont(const std::string& fontName) {
|
||||
font = ThemeManager::GetFont(fontName);
|
||||
textConfig.font = ThemeManager::GetFont(fontName);
|
||||
AutoSize();
|
||||
}
|
||||
|
||||
void Label::SetPreset(const std::string& name) {
|
||||
textConfig = ThemeManager::GetMetric<TextConfig>("/textPresets/" + name, textConfig);
|
||||
AutoSize();
|
||||
}
|
||||
|
||||
void Label::Refresh() { AutoSize(); }
|
||||
|
||||
void Label::PreDrawOffscreen() {
|
||||
buffer.reset(); // I guess?
|
||||
}
|
||||
@ -41,7 +48,7 @@ void Label::PreDraw() {
|
||||
buffer = std::make_unique<gfx::DrawContextCanvas>(rect.size + Vector2(0, 8));
|
||||
buffer->Clear();
|
||||
GFXManager::PushContext(buffer.get());
|
||||
font->Print(buffer->rect, text, 1, color, justification, borderColor);
|
||||
textConfig.Print(buffer->rect, text, justification);
|
||||
GFXManager::PopContext();
|
||||
}
|
||||
}
|
||||
@ -51,7 +58,6 @@ void Label::Draw() {
|
||||
if (buffer) {
|
||||
buffer->Draw(VRect(rect.pos, buffer->rect.size));
|
||||
} else {
|
||||
font->Print(rect, text, 1, color, justification, borderColor);
|
||||
textConfig.Print(rect, text, justification);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,13 +19,10 @@ namespace starlight {
|
||||
|
||||
public:
|
||||
std::string text = "";
|
||||
gfx::ThemeRef<gfx::Font> font;
|
||||
TextConfig textConfig;
|
||||
|
||||
std::unique_ptr<gfx::DrawContextCanvas> buffer;
|
||||
|
||||
Color color = Color::white;
|
||||
Color borderColor = Color::transparent;
|
||||
|
||||
bool autoSizeV = false;
|
||||
Vector2 justification = Vector2::half;
|
||||
|
||||
@ -34,6 +31,9 @@ namespace starlight {
|
||||
|
||||
void SetText(const std::string& text);
|
||||
void SetFont(const std::string& fontName);
|
||||
void SetPreset(const std::string& name);
|
||||
|
||||
void Refresh();
|
||||
|
||||
void PreDrawOffscreen() override;
|
||||
void PreDraw() override;
|
||||
|
@ -2,13 +2,18 @@
|
||||
|
||||
|
||||
roadmap to first release, in no particular order {
|
||||
add touch interceptor (and possibly dimming "shroud") to modal box
|
||||
make more stuff use theme metrics (particularly default text configs) {
|
||||
label defaults
|
||||
make more stuff use theme metrics {
|
||||
dialog layouts(...?)
|
||||
}
|
||||
finish implementing OSK! {
|
||||
make backspace and enter actually do something
|
||||
abstract osk input actions into a separate object/class heirarchy
|
||||
polish!
|
||||
InputManager::OpenKeyboard
|
||||
}
|
||||
implement OSK!
|
||||
|
||||
add license!! (MIT?)
|
||||
ADD README.MD PLS
|
||||
} and some lesser priority things {
|
||||
add language config and atlas support
|
||||
maybe implement some way of "knocking out" and replacing metrics during runtime for theme switching
|
||||
@ -28,7 +33,7 @@ form system { framework done apart from some small api changes
|
||||
|
||||
|
||||
today's agenda {
|
||||
FSHelper, recursive directory assertion etc.
|
||||
...
|
||||
} then {
|
||||
change Label to move the rect instead of resizing to accomodate drops (add an offset thing to Font)
|
||||
kill scroll velocity when hitting the edge (or rapid decel)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "starlight/ui/Label.h"
|
||||
|
||||
#include "starlight/dialog/MessageBox.h"
|
||||
#include "starlight/dialog/OSK.h"
|
||||
|
||||
using starlight::Vector2;
|
||||
using starlight::VRect;
|
||||
@ -49,20 +50,32 @@ void Core::Init() {
|
||||
|
||||
auto button = std::make_shared<sl::ui::Button>(VRect(64,80,128,32));
|
||||
button->SetText("I'm a button.");
|
||||
button->eOnTap = [label](auto& btn){
|
||||
button->eOnTap = [](auto& btn){
|
||||
auto form = std::make_shared<sl::ui::Form>(true);
|
||||
auto label = std::make_shared<sl::ui::Label>(VRect(0,0,320,0));
|
||||
label->autoSizeV = true;
|
||||
label->SetText("This is a form, coming in and nuking the non-form UI elements. Whoops.");
|
||||
form->touchScreen->Add(label);
|
||||
auto xbtn = std::make_shared<sl::ui::Button>(VRect(0,0,32,32));
|
||||
xbtn->SetText(" ");
|
||||
auto xbtn = std::make_shared<sl::ui::Button>(VRect(4,24,32,32));
|
||||
//xbtn->SetText(" ");
|
||||
xbtn->eOnTap = [](auto& btn){
|
||||
Application::Quit();
|
||||
};
|
||||
form->touchScreen->Add(xbtn);
|
||||
form->Open();
|
||||
auto msg = sl::dialog::MessageBox::New(sl::dialog::MessageBox::OkCancel, "This is a modal dialog!\n\n\n\nScrolly\n\n\n\nscrolly\n\n\n\nscrolly\n\n\n\nscrolly\n\n\n\nscroll!");
|
||||
msg->Open();
|
||||
//auto msg = sl::dialog::MessageBox::New(sl::dialog::MessageBox::OkCancel, "This is a modal dialog!\n\n\n\nScrolly\n\n\n\nscrolly\n\n\n\nscrolly\n\n\n\nscrolly\n\n\n\nscroll!");
|
||||
//msg->Open();
|
||||
auto tlbl = std::make_shared<sl::ui::Label>(VRect(2, 2, 396, 0));
|
||||
tlbl->autoSizeV = true;
|
||||
tlbl->SetPreset("normal.16");
|
||||
tlbl->justification = Vector2::zero;
|
||||
tlbl->textConfig.borderColor = Color::black;
|
||||
tlbl->SetText("3DS:~# ");
|
||||
form->topScreen->Add(tlbl);
|
||||
auto kb = sl::dialog::OSK::New(&(tlbl->text), [tlbl](){tlbl->Refresh();});
|
||||
kb->Open();
|
||||
|
||||
label->SetFont("default.16");
|
||||
/*label->SetFont("default.16");
|
||||
btn.SetText("I was pressed!");
|
||||
btn.eOnTap = [label](auto& btn){
|
||||
label->borderColor = Color::black;
|
||||
@ -89,7 +102,7 @@ void Core::Init() {
|
||||
msg->Open();
|
||||
};
|
||||
};
|
||||
};
|
||||
};*/
|
||||
};
|
||||
container->Add(button);
|
||||
|
||||
@ -100,7 +113,7 @@ void Core::Init() {
|
||||
topScreen->Add(parallax);
|
||||
|
||||
auto pipf = std::make_shared<sl::ui::Label>(VRect(0,0,400,240));
|
||||
pipf->SetFont("default.16"); pipf->borderColor = Color::black;
|
||||
pipf->SetPreset("normal.16"); pipf->textConfig.borderColor = Color::black;
|
||||
//pipf->SetText("I am the very model of something on the top screen. :D\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
|
||||
std::stringstream st;
|
||||
//st << "dir: " << Path("sdmc:/.starlight").IsDirectory() << "\nfile: " << Path("sdmc:/arm9loaderhax.bin").IsFile();
|
||||
|
BIN
themes/default/decorations/dialog.modal-cover.png
Normal file
BIN
themes/default/decorations/dialog.modal-cover.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 794 B |
BIN
themes/default/decorations/dialog.modal-cover.xcf
Normal file
BIN
themes/default/decorations/dialog.modal-cover.xcf
Normal file
Binary file not shown.
@ -29,5 +29,11 @@
|
||||
}
|
||||
},
|
||||
|
||||
"dialogs" : {
|
||||
"messageBox" : {
|
||||
"size" : [240, 160]
|
||||
}
|
||||
},
|
||||
|
||||
"":""
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user