Add main screen
This commit is contained in:
@@ -62,7 +62,7 @@ set(CROSSLANG_ENABLE_BINARIES OFF)
|
|||||||
|
|
||||||
FetchContent_MakeAvailable(TessesCrossLang)
|
FetchContent_MakeAvailable(TessesCrossLang)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} src/main.cpp src/bigscreenwindow.cpp src/bigscreenplayer.cpp src/button.cpp src/vgrid.cpp src/hgrid.cpp src/clipper.cpp src/font.cpp src/text.cpp)
|
add_executable(${PROJECT_NAME} src/main.cpp src/bigscreenwindow.cpp src/bigscreenplayer.cpp src/button.cpp src/vgrid.cpp src/hgrid.cpp src/clipper.cpp src/font.cpp src/text.cpp src/textbox.cpp)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC crosslang_static)
|
target_link_libraries(${PROJECT_NAME} PUBLIC crosslang_static)
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,8 @@ namespace Tesses::BigScreen {
|
|||||||
|
|
||||||
int MinHeight();
|
int MinHeight();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Button : public Widget, public std::enable_shared_from_this<Button>
|
class Button : public Widget, public std::enable_shared_from_this<Button>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -192,7 +194,6 @@ namespace Tesses::BigScreen {
|
|||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
|
|
||||||
std::shared_ptr<Widget> page;
|
std::shared_ptr<Widget> page;
|
||||||
bool running=true;
|
|
||||||
Widget* current = nullptr;
|
Widget* current = nullptr;
|
||||||
std::shared_ptr<FontCache> fc;
|
std::shared_ptr<FontCache> fc;
|
||||||
SDL_Color color=COLOR_BGLIGHT;
|
SDL_Color color=COLOR_BGLIGHT;
|
||||||
@@ -209,6 +210,7 @@ namespace Tesses::BigScreen {
|
|||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
~BigScreenWindow();
|
~BigScreenWindow();
|
||||||
|
std::shared_ptr<Widget> GetWidget();
|
||||||
void SetWidget(std::shared_ptr<Widget> widget);
|
void SetWidget(std::shared_ptr<Widget> widget);
|
||||||
void DrawRectThick(SDL_Rect rect, int sz);
|
void DrawRectThick(SDL_Rect rect, int sz);
|
||||||
std::shared_ptr<BigScreenWindow> GetRoot();
|
std::shared_ptr<BigScreenWindow> GetRoot();
|
||||||
@@ -216,6 +218,8 @@ namespace Tesses::BigScreen {
|
|||||||
void SetBackColor(SDL_Color color);
|
void SetBackColor(SDL_Color color);
|
||||||
void SetBackColor(std::string color);
|
void SetBackColor(std::string color);
|
||||||
|
|
||||||
|
void SetPage(std::string name, std::shared_ptr<Widget> widget);
|
||||||
|
void Close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -230,16 +234,58 @@ namespace Tesses::BigScreen {
|
|||||||
|
|
||||||
int tex_w = -1, tex_h = -1;
|
int tex_w = -1, tex_h = -1;
|
||||||
|
|
||||||
|
bool controls=false;
|
||||||
|
bool paused = false;
|
||||||
|
bool seeking=false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mpv_handle* GetMPVHandle();
|
mpv_handle* GetMPVHandle();
|
||||||
VideoPlayerWidget();
|
VideoPlayerWidget();
|
||||||
EventResult Event(SDL_Event& event,SDL_Rect& rect);
|
EventResult Event(SDL_Event& event,SDL_Rect& rect);
|
||||||
|
void SetPrev(std::shared_ptr<Widget> w);
|
||||||
|
std::shared_ptr<Widget> GetPrev();
|
||||||
void Draw(SDL_Rect& rect);
|
void Draw(SDL_Rect& rect);
|
||||||
void LoadFile(std::string file);
|
void LoadFile(std::string file);
|
||||||
~VideoPlayerWidget();
|
~VideoPlayerWidget();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TextBox : public Widget, public std::enable_shared_from_this<TextBox>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string text;
|
||||||
|
public:
|
||||||
|
TextBox()=default;
|
||||||
|
EventResult Event(SDL_Event& event,SDL_Rect& rect);
|
||||||
|
void Draw(SDL_Rect& rect);
|
||||||
|
std::string GetText();
|
||||||
|
void SetText(std::string text);
|
||||||
|
int MinWidth();
|
||||||
|
int MinHeight();
|
||||||
|
|
||||||
|
class TextBoxDialog : public Widget {
|
||||||
|
std::shared_ptr<TextBox> tb;
|
||||||
|
std::shared_ptr<Widget> page;
|
||||||
|
std::shared_ptr<VGrid> grid;
|
||||||
|
size_t cursor;
|
||||||
|
|
||||||
|
bool shift=false;
|
||||||
|
int x=0;
|
||||||
|
int y=-1;
|
||||||
|
|
||||||
|
void Append(char c);
|
||||||
|
void HandleKey();
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextBoxDialog(std::shared_ptr<TextBox> tb, std::shared_ptr<Widget> page);
|
||||||
|
EventResult Event(SDL_Event& event,SDL_Rect& rect);
|
||||||
|
void Draw(SDL_Rect& rect);
|
||||||
|
~TextBoxDialog()=default;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Clipper {
|
class Clipper {
|
||||||
SDL_Rect theRect;
|
SDL_Rect theRect;
|
||||||
SDL_Renderer* renderer;
|
SDL_Renderer* renderer;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ namespace Tesses::BigScreen {
|
|||||||
//"/home/mike/Music/dir/Vids/Chicken.mp4";
|
//"/home/mike/Music/dir/Vids/Chicken.mp4";
|
||||||
mpv = mpv_create();
|
mpv = mpv_create();
|
||||||
mpv_set_option_string(mpv, "vo", "libmpv");
|
mpv_set_option_string(mpv, "vo", "libmpv");
|
||||||
|
|
||||||
if (mpv_initialize(mpv) < 0)
|
if (mpv_initialize(mpv) < 0)
|
||||||
throw std::runtime_error("mpv init failed");
|
throw std::runtime_error("mpv init failed");
|
||||||
|
|
||||||
@@ -36,46 +37,108 @@ namespace Tesses::BigScreen {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const int CONTROLS_HEIGHT = 16;
|
||||||
EventResult VideoPlayerWidget::Event(SDL_Event& event, SDL_Rect& rect)
|
EventResult VideoPlayerWidget::Event(SDL_Event& event, SDL_Rect& rect)
|
||||||
{
|
{
|
||||||
auto window = this->GetRoot();
|
auto window = this->GetRoot();
|
||||||
if(window == nullptr) return EventResult::Ignored;
|
if(window == nullptr) return EventResult::Ignored;
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
this->seeking=false;
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
{
|
||||||
|
this->controls = (event.motion.x > rect.x && event.motion.y >= (rect.h - CONTROLS_HEIGHT) + rect.y && event.button.x < rect.x+rect.w && event.motion.y < rect.y+rect.h);
|
||||||
|
|
||||||
case SDL_KEYDOWN:
|
if(seeking && event.motion.x >= rect.x && event.motion.x < rect.x+rect.w && rect.w > 0)
|
||||||
if(event.key.keysym.sym == SDLK_ESCAPE)
|
|
||||||
{
|
{
|
||||||
window->SetWidget(nullptr);
|
double pos = (double)(event.motion.x - rect.x) / (double)rect.w;
|
||||||
|
double length = 0;
|
||||||
|
mpv_get_property(mpv, "duration", mpv_format::MPV_FORMAT_DOUBLE, &length);
|
||||||
|
|
||||||
|
std::string seek = std::to_string(length*pos);
|
||||||
|
|
||||||
|
const char *cmd_seek[] = {"seek", seek.c_str(), "absolute",NULL};
|
||||||
|
mpv_command_async(mpv, 0, cmd_seek);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
if(event.button.x >= rect.x && event.button.y >= rect.y && event.button.x < rect.x+rect.w && event.button.y < rect.y+rect.h)
|
||||||
|
{
|
||||||
|
window->SetCurrent(this);
|
||||||
|
if(event.button.y >= rect.y+(rect.h-CONTROLS_HEIGHT) && rect.w > 0)
|
||||||
|
{
|
||||||
|
this->seeking=true;
|
||||||
|
double pos = (double)(event.button.x - rect.x) / (double)rect.w;
|
||||||
|
double length = 0;
|
||||||
|
mpv_get_property(mpv, "duration", mpv_format::MPV_FORMAT_DOUBLE, &length);
|
||||||
|
|
||||||
|
std::string seek = std::to_string(length*pos);
|
||||||
|
|
||||||
|
const char *cmd_seek[] = {"seek", seek.c_str(), "absolute",NULL};
|
||||||
|
mpv_command_async(mpv, 0, cmd_seek);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char *cmd_pause[] = {"cycle", "pause", NULL};
|
||||||
|
mpv_command_async(mpv, 0, cmd_pause);
|
||||||
|
}
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
{
|
||||||
|
if(!window->IsCurrent(this)) return EventResult::Ignored;
|
||||||
|
|
||||||
|
if(event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN)
|
||||||
|
{
|
||||||
|
return EventResult::ParentDo;
|
||||||
|
}
|
||||||
|
|
||||||
if(event.key.keysym.sym == SDLK_LEFT)
|
if(event.key.keysym.sym == SDLK_LEFT)
|
||||||
{
|
{
|
||||||
const char *seek[] = {"seek", "-10", NULL};
|
const char *seek[] = {"seek", "-10", NULL};
|
||||||
mpv_command_async(mpv, 0, seek);
|
mpv_command_async(mpv, 0, seek);
|
||||||
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
if(event.key.keysym.sym == SDLK_RIGHT)
|
if(event.key.keysym.sym == SDLK_RIGHT)
|
||||||
{
|
{
|
||||||
const char *seek[] = {"seek", "+10", NULL};
|
const char *seek[] = {"seek", "+10", NULL};
|
||||||
mpv_command_async(mpv, 0, seek);
|
mpv_command_async(mpv, 0, seek);
|
||||||
|
|
||||||
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
if (event.key.keysym.sym == SDLK_SPACE) {
|
if (event.key.keysym.sym == SDLK_SPACE) {
|
||||||
const char *cmd_pause[] = {"cycle", "pause", NULL};
|
const char *cmd_pause[] = {"cycle", "pause", NULL};
|
||||||
mpv_command_async(mpv, 0, cmd_pause);
|
mpv_command_async(mpv, 0, cmd_pause);
|
||||||
|
|
||||||
|
mpv_get_property(mpv, "pause", mpv_format::MPV_FORMAT_FLAG, &paused);
|
||||||
|
|
||||||
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return EventResult::Handled;
|
return EventResult::Ignored;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoPlayerWidget::Draw(SDL_Rect& rect)
|
void VideoPlayerWidget::Draw(SDL_Rect& rect)
|
||||||
{
|
{
|
||||||
auto window = this->GetRoot();
|
auto window = this->GetRoot();
|
||||||
if(window == nullptr) return;
|
if(window == nullptr) return;
|
||||||
|
|
||||||
|
|
||||||
|
mpv_get_property(mpv, "pause", mpv_format::MPV_FORMAT_FLAG, &paused);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int w=rect.w, h=rect.h;
|
int w=rect.w, h=rect.h;
|
||||||
if (!tex || tex_w != w || tex_h != h) {
|
if (!tex || tex_w != w || tex_h != h) {
|
||||||
SDL_DestroyTexture(tex);
|
SDL_DestroyTexture(tex);
|
||||||
@@ -114,9 +177,45 @@ namespace Tesses::BigScreen {
|
|||||||
if(tex)
|
if(tex)
|
||||||
SDL_RenderCopy(window->GetRenderer(), tex, NULL, &rect);
|
SDL_RenderCopy(window->GetRenderer(), tex, NULL, &rect);
|
||||||
|
|
||||||
|
SDL_Rect controls = {
|
||||||
|
.x = rect.x,
|
||||||
|
.y = rect.y + (rect.h-CONTROLS_HEIGHT),
|
||||||
|
.w = rect.w,
|
||||||
|
.h = CONTROLS_HEIGHT
|
||||||
|
};
|
||||||
|
if(this->controls || this->paused)
|
||||||
|
{
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_HIGHLIGHT.r, COLOR_HIGHLIGHT.g, COLOR_HIGHLIGHT.b, COLOR_HIGHLIGHT.a);
|
||||||
|
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &controls);
|
||||||
|
double length = 0;
|
||||||
|
double time_pos = 0;
|
||||||
|
mpv_get_property(mpv, "duration", mpv_format::MPV_FORMAT_DOUBLE, &length);
|
||||||
|
|
||||||
|
mpv_get_property(mpv,"time-pos",mpv_format::MPV_FORMAT_DOUBLE, &time_pos);
|
||||||
|
|
||||||
|
|
||||||
|
if(length > 0)
|
||||||
|
{
|
||||||
|
double offset = time_pos / length;
|
||||||
|
if(offset < 0.0)
|
||||||
|
offset = 0.0;
|
||||||
|
if(offset > 1.0)
|
||||||
|
offset = 1.0;
|
||||||
|
|
||||||
|
SDL_Rect r2 = {
|
||||||
|
.x=controls.x,
|
||||||
|
.y=controls.y,
|
||||||
|
.w=offset*rect.w,
|
||||||
|
.h=controls.h
|
||||||
|
};
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_PRIMARY.r, COLOR_PRIMARY.g, COLOR_PRIMARY.b, COLOR_PRIMARY.a);
|
||||||
|
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDL_RenderPresent(window->GetRenderer());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoPlayerWidget::LoadFile(std::string file)
|
void VideoPlayerWidget::LoadFile(std::string file)
|
||||||
|
|||||||
@@ -30,16 +30,20 @@ namespace Tesses::BigScreen
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Widget> BigScreenWindow::GetWidget()
|
||||||
|
{
|
||||||
|
return this->page;
|
||||||
|
}
|
||||||
|
|
||||||
BigScreenWindow::BigScreenWindow()
|
BigScreenWindow::BigScreenWindow()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
window = SDL_CreateWindow("Tesses Big Screen", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE);
|
window = SDL_CreateWindow("Tesses Big Screen", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_FULLSCREEN);
|
||||||
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
|
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
|
||||||
|
this->fc = std::make_shared<FontCache>(renderer, 36);
|
||||||
|
|
||||||
this->fc = std::make_shared<FontCache>(renderer, 24);
|
|
||||||
|
|
||||||
running=true;
|
|
||||||
}
|
}
|
||||||
std::shared_ptr<FontCache> BigScreenWindow::GetFont()
|
std::shared_ptr<FontCache> BigScreenWindow::GetFont()
|
||||||
{
|
{
|
||||||
@@ -59,7 +63,7 @@ namespace Tesses::BigScreen
|
|||||||
|
|
||||||
void BigScreenWindow::Run()
|
void BigScreenWindow::Run()
|
||||||
{
|
{
|
||||||
while(running)
|
while(Tesses::Framework::TF_IsRunning())
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
@@ -84,7 +88,7 @@ namespace Tesses::BigScreen
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Tesses::Framework::TF_Sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,8 +135,7 @@ namespace Tesses::BigScreen
|
|||||||
{
|
{
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
{
|
{
|
||||||
|
Tesses::Framework::TF_SetIsRunning(false);
|
||||||
running=false;
|
|
||||||
|
|
||||||
return EventResult::Handled;
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
@@ -182,8 +185,10 @@ namespace Tesses::BigScreen
|
|||||||
|
|
||||||
this->page = page;
|
this->page = page;
|
||||||
if(page)
|
if(page)
|
||||||
|
{
|
||||||
page->parent = this->weak_from_this();
|
page->parent = this->weak_from_this();
|
||||||
|
SetCurrent(page.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -214,4 +219,21 @@ namespace Tesses::BigScreen
|
|||||||
return mytype;
|
return mytype;
|
||||||
return std::shared_ptr<BigScreenWindow>();
|
return std::shared_ptr<BigScreenWindow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BigScreenWindow::SetPage(std::string name, std::shared_ptr<Widget> widget)
|
||||||
|
{
|
||||||
|
auto cur = this->GetWidget();
|
||||||
|
|
||||||
|
auto vgrid = std::make_shared<VGrid>();
|
||||||
|
auto hgrid = std::make_shared<HGrid>();
|
||||||
|
hgrid->AddChild(std::make_shared<Button>("<-",[cur](std::shared_ptr<Widget> w)->void {
|
||||||
|
auto win = w->GetRoot();
|
||||||
|
if(win)
|
||||||
|
win->SetWidget(cur);
|
||||||
|
}),0);
|
||||||
|
hgrid->AddChild(std::make_shared<Text>(name),0);
|
||||||
|
vgrid->AddChild(hgrid,0);
|
||||||
|
vgrid->AddChild(widget,GRID_STRETCH);
|
||||||
|
this->SetWidget(vgrid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -87,9 +87,10 @@ namespace Tesses::BigScreen
|
|||||||
{
|
{
|
||||||
if(event.button.x >= rect.x && event.button.y >= rect.y && event.button.x < rect.x+rect.w && event.button.y < rect.y+rect.h)
|
if(event.button.x >= rect.x && event.button.y >= rect.y && event.button.x < rect.x+rect.w && event.button.y < rect.y+rect.h)
|
||||||
{
|
{
|
||||||
if(this->cb) this->cb(this->shared_from_this());
|
|
||||||
|
|
||||||
window->SetCurrent(this);
|
window->SetCurrent(this);
|
||||||
|
if(this->cb) this->cb(this->shared_from_this());
|
||||||
|
|
||||||
return EventResult::Handled;
|
return EventResult::Handled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,7 +146,7 @@ namespace Tesses::BigScreen
|
|||||||
rect.w-=4;
|
rect.w-=4;
|
||||||
rect.h-=4;
|
rect.h-=4;
|
||||||
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_BORDER.r, COLOR_BORDER.g, COLOR_BORDER.b, COLOR_BORDER.a);
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_BORDER.r, COLOR_BORDER.g, COLOR_BORDER.b, COLOR_BORDER.a);
|
||||||
window->DrawRectThick(rect, 2);
|
window->DrawRectThick(rect, 3);
|
||||||
rect.x-=2;
|
rect.x-=2;
|
||||||
rect.y-=2;
|
rect.y-=2;
|
||||||
rect.w+=4;
|
rect.w+=4;
|
||||||
@@ -188,7 +189,7 @@ namespace Tesses::BigScreen
|
|||||||
this->child->parent = weak_from_this();
|
this->child->parent = weak_from_this();
|
||||||
|
|
||||||
if(this->child)
|
if(this->child)
|
||||||
return this->child->MinWidth() + 24;
|
return this->child->MinWidth() + 16;
|
||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +199,7 @@ namespace Tesses::BigScreen
|
|||||||
this->child->parent = weak_from_this();
|
this->child->parent = weak_from_this();
|
||||||
|
|
||||||
if(this->child)
|
if(this->child)
|
||||||
return this->child->MinHeight() + 24;
|
return this->child->MinHeight() + 16;
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ bool TryParseSDLColor(std::string str, SDL_Color& col)
|
|||||||
{
|
{
|
||||||
str = HU::Replace(str," ","");
|
str = HU::Replace(str," ","");
|
||||||
//rgba(255,255,255,1.0)
|
//rgba(255,255,255,1.0)
|
||||||
//rgb(197, 30, 30)
|
//rgb(197,30,30)
|
||||||
//#rgb
|
//#rgb
|
||||||
//#rgba
|
//#rgba
|
||||||
//#rrggbb
|
//#rrggbb
|
||||||
|
|||||||
291
src/main.cpp
291
src/main.cpp
@@ -1,57 +1,260 @@
|
|||||||
#include "bigscreen.hpp"
|
#include "bigscreen.hpp"
|
||||||
|
|
||||||
|
using namespace Tesses::BigScreen;
|
||||||
|
|
||||||
|
std::vector<std::string> pages = {
|
||||||
|
"VIDEOS",
|
||||||
|
"MUSIC",
|
||||||
|
"PICTURES",
|
||||||
|
"PLUGINS",
|
||||||
|
"SETTINGS",
|
||||||
|
"EXIT"
|
||||||
|
};
|
||||||
|
|
||||||
|
const int PAGE_VIDEO = 0;
|
||||||
|
const int PAGE_MUSIC = 1;
|
||||||
|
const int PAGE_PICTURES = 2;
|
||||||
|
const int PAGE_PLUGINS = 3;
|
||||||
|
const int PAGE_SETTINGS = 4;
|
||||||
|
const int PAGE_EXIT = 5;
|
||||||
|
|
||||||
|
class Home : public Widget, public std::enable_shared_from_this<Home> {
|
||||||
|
size_t pageIdx = 0;
|
||||||
|
public:
|
||||||
|
bool Click(SDL_Rect& rect,int x, int y)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return false;
|
||||||
|
auto font = window->GetFont();
|
||||||
|
|
||||||
|
|
||||||
|
auto charWidth = font->MaxWidth();
|
||||||
|
auto charHeight = font->MaxHeight();
|
||||||
|
|
||||||
|
auto yButtons = (rect.h-(rect.h/3))+rect.y;
|
||||||
|
|
||||||
|
auto centerBtnWidth = (charWidth * 9)+16;
|
||||||
|
|
||||||
|
auto centerBtnX = ((rect.w/2) - (centerBtnWidth / 2))+rect.x;
|
||||||
|
|
||||||
|
auto sideBtnWidth = (charWidth * 2)+16;
|
||||||
|
auto leftButtonX = centerBtnX - (sideBtnWidth+16);
|
||||||
|
auto rightButtonX = centerBtnX + centerBtnWidth + 16;
|
||||||
|
|
||||||
|
|
||||||
|
SDL_Rect rect2 = {
|
||||||
|
.x = centerBtnX,
|
||||||
|
.y=yButtons,
|
||||||
|
.w = centerBtnWidth,
|
||||||
|
.h=charHeight+16
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if(x >= rect2.x && y >= rect2.y && x < rect2.x + rect2.w && y < rect2.y + rect2.h)
|
||||||
|
{
|
||||||
|
Select();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rect2 = {
|
||||||
|
.x = leftButtonX,
|
||||||
|
.y=yButtons,
|
||||||
|
.w = sideBtnWidth,
|
||||||
|
.h=charHeight+16
|
||||||
|
};
|
||||||
|
|
||||||
|
if(x >= rect2.x && y >= rect2.y && x < rect2.x + rect2.w && y < rect2.y + rect2.h)
|
||||||
|
{
|
||||||
|
if(pageIdx > 0) pageIdx--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect2 = {
|
||||||
|
.x = rightButtonX,
|
||||||
|
.y=yButtons,
|
||||||
|
.w = sideBtnWidth,
|
||||||
|
.h=charHeight+16
|
||||||
|
};
|
||||||
|
|
||||||
|
if(x >= rect2.x && y >= rect2.y && x < rect2.x + rect2.w && y < rect2.y + rect2.h)
|
||||||
|
{
|
||||||
|
if(pageIdx+1 < pages.size()) pageIdx++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void Select()
|
||||||
|
{
|
||||||
|
auto window=GetRoot();
|
||||||
|
if(!window) return;
|
||||||
|
|
||||||
|
switch(pageIdx)
|
||||||
|
{
|
||||||
|
case PAGE_VIDEO:
|
||||||
|
{
|
||||||
|
window->SetPage("Videos", nullptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PAGE_EXIT:
|
||||||
|
Tesses::Framework::TF_SetIsRunning(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventResult Event(SDL_Event& event,SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return EventResult::Ignored;
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
return Click(rect,event.button.x,event.button.y) ? EventResult::Handled : EventResult::Ignored;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
{
|
||||||
|
switch(event.key.keysym.scancode)
|
||||||
|
{
|
||||||
|
case SDL_SCANCODE_ESCAPE:
|
||||||
|
{
|
||||||
|
Tesses::Framework::TF_SetIsRunning(false);
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_LEFT:
|
||||||
|
{
|
||||||
|
if(pageIdx > 0) pageIdx--;
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_RIGHT:
|
||||||
|
{
|
||||||
|
if(pageIdx+1 < pages.size()) pageIdx++;
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_SPACE:
|
||||||
|
{
|
||||||
|
Select();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return EventResult::Ignored;
|
||||||
|
}
|
||||||
|
void Draw(SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return;
|
||||||
|
auto font = window->GetFont();
|
||||||
|
|
||||||
|
auto dt= Tesses::Framework::Date::DateTime::Now();
|
||||||
|
|
||||||
|
|
||||||
|
std::string dateTime = dt.ToString(
|
||||||
|
"%I:%M:%S %p%n%a, %b %d, %Y"
|
||||||
|
);
|
||||||
|
|
||||||
|
int myW=0, myH=0;
|
||||||
|
|
||||||
|
font->CalculateSize(dateTime,myW,myH);
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(), (rect.x + rect.w - myW) - 24, rect.y+12,dateTime,COLOR_TEXT);
|
||||||
|
|
||||||
|
|
||||||
|
font->CalculateSize("Tesses BigScreen",myW, myH);
|
||||||
|
|
||||||
|
myW = ((rect.w / 2) - (myW/2)) + rect.x;
|
||||||
|
myH = (rect.h/4) + rect.y;
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(), myW,myH, "Tesses BigScreen", COLOR_TEXT);
|
||||||
|
|
||||||
|
auto charWidth = font->MaxWidth();
|
||||||
|
auto charHeight = font->MaxHeight();
|
||||||
|
|
||||||
|
auto yButtons = (rect.h-(rect.h/3))+rect.y;
|
||||||
|
|
||||||
|
auto centerBtnWidth = (charWidth * 9)+16;
|
||||||
|
|
||||||
|
auto centerBtnX = ((rect.w/2) - (centerBtnWidth / 2))+rect.x;
|
||||||
|
|
||||||
|
auto sideBtnWidth = (charWidth * 2)+16;
|
||||||
|
auto leftButtonX = centerBtnX - (sideBtnWidth+16);
|
||||||
|
auto rightButtonX = centerBtnX + centerBtnWidth + 16;
|
||||||
|
|
||||||
|
|
||||||
|
SDL_Rect rect2 = {
|
||||||
|
.x = centerBtnX,
|
||||||
|
.y=yButtons,
|
||||||
|
.w = centerBtnWidth,
|
||||||
|
.h=charHeight+16
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_PRIMARY.r, COLOR_PRIMARY.g, COLOR_PRIMARY.b,COLOR_PRIMARY.a);
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &rect2);
|
||||||
|
|
||||||
|
font->CalculateSize(pages[this->pageIdx],myW,myH);
|
||||||
|
|
||||||
|
myW = ((rect2.w/2) - (myW/2))+rect2.x;
|
||||||
|
|
||||||
|
myH = ((rect2.h/2) - (myH/2))+rect2.y;
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(),myW,myH,pages[this->pageIdx],COLOR_TEXT);
|
||||||
|
|
||||||
|
|
||||||
|
rect2 = {
|
||||||
|
.x = leftButtonX,
|
||||||
|
.y=yButtons,
|
||||||
|
.w = sideBtnWidth,
|
||||||
|
.h=charHeight+16
|
||||||
|
};
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &rect2);
|
||||||
|
font->CalculateSize("<-",myW,myH);
|
||||||
|
|
||||||
|
myW = ((rect2.w/2) - (myW/2))+rect2.x;
|
||||||
|
|
||||||
|
myH = ((rect2.h/2) - (myH/2))+rect2.y;
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(),myW,myH,"<-",COLOR_TEXT);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rect2 = {
|
||||||
|
.x = rightButtonX,
|
||||||
|
.y=yButtons,
|
||||||
|
.w = sideBtnWidth,
|
||||||
|
.h=charHeight+16
|
||||||
|
};
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &rect2);
|
||||||
|
|
||||||
|
font->CalculateSize("->",myW,myH);
|
||||||
|
|
||||||
|
myW = ((rect2.w/2) - (myW/2))+rect2.x;
|
||||||
|
|
||||||
|
myH = ((rect2.h/2) - (myH/2))+rect2.y;
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(),myW,myH,"->",COLOR_TEXT);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
Tesses::Framework::TF_Init();
|
||||||
TTF_Init();
|
TTF_Init();
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_EVERYTHING);
|
SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
using namespace Tesses::BigScreen;
|
|
||||||
auto window = std::make_shared<BigScreenWindow>();
|
|
||||||
/*window->SetWidget(std::make_shared<Button>("My Button",[](std::shared_ptr<Tesses::BigScreen::Widget> w)->void{
|
|
||||||
std::cout << "Hi" << std::endl;
|
|
||||||
}));*/
|
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<VGrid> vgrid = std::make_shared<VGrid>();
|
|
||||||
|
|
||||||
vgrid->AddChild(std::make_shared<Text>("Label"),0);
|
auto win = std::make_shared<BigScreenWindow>();
|
||||||
|
win->SetWidget(std::make_shared<Home>());
|
||||||
|
win->Run();
|
||||||
|
|
||||||
vgrid->AddChild(std::make_shared<Button>("My Button",[](std::shared_ptr<Widget> w)->void{
|
|
||||||
std::cout <<"My Button" <<std::endl;
|
|
||||||
}), 0);
|
|
||||||
vgrid->AddChild(std::make_shared<Text>("Label 2"),0);
|
|
||||||
vgrid->AddChild(std::make_shared<Button>("My Button 2",[](std::shared_ptr<Widget> w)->void{
|
|
||||||
std::cout <<"My Button 2" <<std::endl;
|
|
||||||
}), 0);
|
|
||||||
|
|
||||||
auto hgrid = std::make_shared<HGrid>();
|
|
||||||
|
|
||||||
vgrid->AddChild(nullptr, GRID_STRETCH);
|
|
||||||
|
|
||||||
hgrid->AddChild(nullptr,GRID_STRETCH);
|
|
||||||
|
|
||||||
hgrid->AddChild(std::make_shared<Button>("<-", [](std::shared_ptr<Widget> widget)->void {
|
|
||||||
std::cout << "<-" << std::endl;
|
|
||||||
}),0);
|
|
||||||
hgrid->AddChild(nullptr,16);
|
|
||||||
hgrid->AddChild(std::make_shared<Button>("OK", [](std::shared_ptr<Widget> widget)->void {
|
|
||||||
std::cout << "OK" << std::endl;
|
|
||||||
}),0);
|
|
||||||
|
|
||||||
hgrid->AddChild(nullptr,16);
|
|
||||||
hgrid->AddChild(std::make_shared<Button>("Cancel", [](std::shared_ptr<Widget> widget)->void {
|
|
||||||
std::cout << "Cancel" << std::endl;
|
|
||||||
}),0);
|
|
||||||
|
|
||||||
|
|
||||||
hgrid->AddChild(nullptr, 32);
|
|
||||||
|
|
||||||
vgrid->AddChild(hgrid, 0);
|
|
||||||
|
|
||||||
vgrid->AddChild(nullptr, 32);
|
|
||||||
|
|
||||||
window->SetWidget(vgrid);
|
|
||||||
|
|
||||||
window->Run();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
438
src/textbox.cpp
Normal file
438
src/textbox.cpp
Normal file
@@ -0,0 +1,438 @@
|
|||||||
|
#include "bigscreen.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::BigScreen
|
||||||
|
{
|
||||||
|
EventResult TextBox::Event(SDL_Event& event,SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return EventResult::Ignored;
|
||||||
|
|
||||||
|
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
if(event.button.x >= rect.x && event.button.y >= rect.y && event.button.x < rect.x+rect.w && event.button.y < rect.y+rect.h)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::shared_ptr<TextBoxDialog> dlg = std::make_shared<TextBoxDialog>(shared_from_this(),window->GetWidget());
|
||||||
|
window->SetWidget(dlg);
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
{
|
||||||
|
switch(event.key.keysym.scancode)
|
||||||
|
{
|
||||||
|
case SDL_Scancode::SDL_SCANCODE_SPACE:
|
||||||
|
{
|
||||||
|
if(window->IsCurrent(this))
|
||||||
|
{
|
||||||
|
std::shared_ptr<TextBoxDialog> dlg = std::make_shared<TextBoxDialog>(shared_from_this(),window->GetWidget());
|
||||||
|
window->SetWidget(dlg);
|
||||||
|
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_Scancode::SDL_SCANCODE_UP:
|
||||||
|
case SDL_Scancode::SDL_SCANCODE_DOWN:
|
||||||
|
case SDL_Scancode::SDL_SCANCODE_LEFT:
|
||||||
|
case SDL_Scancode::SDL_SCANCODE_RIGHT:
|
||||||
|
{
|
||||||
|
if(window->IsCurrent(this))
|
||||||
|
return EventResult::ParentDo;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EventResult::Ignored;
|
||||||
|
}
|
||||||
|
std::string TextBox::GetText()
|
||||||
|
{
|
||||||
|
return this->text;
|
||||||
|
}
|
||||||
|
void TextBox::SetText(std::string text)
|
||||||
|
{
|
||||||
|
this->text = text;
|
||||||
|
}
|
||||||
|
void TextBox::Draw(SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return;
|
||||||
|
|
||||||
|
Clipper clipper(window->GetRenderer(),rect);
|
||||||
|
if(clipper.Clip(rect))
|
||||||
|
{
|
||||||
|
auto font = window->GetFont();
|
||||||
|
auto height = (rect.h/2) - (font->MaxHeight()/2);
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(),rect.x+10,rect.y+height,text,COLOR_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_PRIMARY.r, COLOR_PRIMARY.g, COLOR_PRIMARY.b, 255);
|
||||||
|
|
||||||
|
window->DrawRectThick(rect,6);
|
||||||
|
if(window->IsCurrent(this))
|
||||||
|
{
|
||||||
|
rect.x+=2;
|
||||||
|
rect.y+=2;
|
||||||
|
rect.w-=4;
|
||||||
|
rect.h-=4;
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_BORDER.r, COLOR_BORDER.g, COLOR_BORDER.b, COLOR_BORDER.a);
|
||||||
|
window->DrawRectThick(rect, 2);
|
||||||
|
rect.x-=2;
|
||||||
|
rect.y-=2;
|
||||||
|
rect.w+=4;
|
||||||
|
rect.h+=4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextBox::MinWidth()
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return 0;
|
||||||
|
int x=0;
|
||||||
|
int y=0;
|
||||||
|
window->GetFont()->CalculateSize(text,x,y);
|
||||||
|
|
||||||
|
return x+16;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TextBox::MinHeight()
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return 0;
|
||||||
|
int x=0;
|
||||||
|
int y=0;
|
||||||
|
window->GetFont()->CalculateSize(text,x,y);
|
||||||
|
|
||||||
|
return y+16;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const int KEYBOARD_WIDTH = 14;
|
||||||
|
const int KEYBOARD_HEIGHT = 4;
|
||||||
|
|
||||||
|
const char* lower[KEYBOARD_HEIGHT][KEYBOARD_WIDTH]= {
|
||||||
|
{
|
||||||
|
"`","1","2","3","4","5","6","7","8","9","0","-","=","BS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"q","w","e","r","t","y","u","i","o","p","[","]","\\"," ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a","s","d","f","g","h","i","j","k","l",";","'","<-","->"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SH","z","x","c","v","b","n","m",",",".","/","SH"," ","OK",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* upper[KEYBOARD_HEIGHT][KEYBOARD_WIDTH]= {
|
||||||
|
{
|
||||||
|
"~","!","@","#","$","%","^","&","*","(",")","_","+","BS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Q","W","E","R","T","Y","U","I","O","P","{","}","|"," ",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"A","S","D","F","G","H","I","J","K","L",":","\"","<-","->"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SH","Z","X","C","V","B","N","M","<",">","?","SH"," ","OK",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void TextBox::TextBoxDialog::Append(char c)
|
||||||
|
{
|
||||||
|
if(c == '\b')
|
||||||
|
{
|
||||||
|
auto& pos = this->cursor;
|
||||||
|
if(pos >= this->tb->text.size())
|
||||||
|
pos = this->tb->text.size();
|
||||||
|
|
||||||
|
if(pos > 0)
|
||||||
|
{
|
||||||
|
pos--;
|
||||||
|
this->tb->text.erase(pos,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto& pos = this->cursor;
|
||||||
|
if(pos >= this->tb->text.size())
|
||||||
|
pos = this->tb->text.size();
|
||||||
|
|
||||||
|
this->tb->text.insert(pos, {c});
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TextBox::TextBoxDialog::TextBoxDialog(std::shared_ptr<TextBox> tb, std::shared_ptr<Widget> page): tb(tb), page(page)
|
||||||
|
{
|
||||||
|
this->cursor = tb->text.size();
|
||||||
|
|
||||||
|
}
|
||||||
|
void TextBox::TextBoxDialog::HandleKey()
|
||||||
|
{
|
||||||
|
if(y == -1) return;
|
||||||
|
if((x == 0 || x == 11) && y == 3) {
|
||||||
|
shift=!shift;
|
||||||
|
}
|
||||||
|
else if(x==13 && y ==3) {
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return;
|
||||||
|
window->SetWidget(this->page);
|
||||||
|
if(this->tb)
|
||||||
|
window->SetCurrent(this->tb.get());
|
||||||
|
}
|
||||||
|
else if(x == 12 && y == 2)
|
||||||
|
{
|
||||||
|
this->cursor--;
|
||||||
|
if(this->cursor >= this->tb->text.size())
|
||||||
|
this->cursor=0;
|
||||||
|
}
|
||||||
|
else if(x == 13 && y == 2)
|
||||||
|
{
|
||||||
|
this->cursor++;
|
||||||
|
if(this->cursor >= this->tb->text.size())
|
||||||
|
this->cursor=this->tb->text.size();
|
||||||
|
}
|
||||||
|
else if(x == 13 && y == 0)
|
||||||
|
{
|
||||||
|
Append('\b');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(x >= 0 && y >= 0 && x < KEYBOARD_WIDTH && y < KEYBOARD_HEIGHT)
|
||||||
|
Append(((shift ? upper : lower)[y][x])[0]);
|
||||||
|
|
||||||
|
shift=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventResult TextBox::TextBoxDialog::Event(SDL_Event& event,SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return EventResult::Ignored;
|
||||||
|
|
||||||
|
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
{
|
||||||
|
int btnTextSzW=0;
|
||||||
|
int btnTextSzH=0;
|
||||||
|
window->GetFont()->CalculateSize("OO",btnTextSzW,btnTextSzH);
|
||||||
|
int btnSzW = btnTextSzW+16;
|
||||||
|
int btnSzH = btnTextSzW+16;
|
||||||
|
|
||||||
|
int keyboardHeight = (KEYBOARD_HEIGHT * btnSzH) + 16;
|
||||||
|
int keyboardWidth = (KEYBOARD_WIDTH * btnSzW) + 16;
|
||||||
|
|
||||||
|
int keyboardX = ((rect.w/2) - (keyboardWidth/2))+rect.x;
|
||||||
|
int keyboardY = rect.y+(rect.h-keyboardHeight);
|
||||||
|
|
||||||
|
for(int y = 0; y < KEYBOARD_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for(int x = 0; x < KEYBOARD_WIDTH; x++)
|
||||||
|
{
|
||||||
|
auto keyX = keyboardX + (x*btnSzW);
|
||||||
|
auto keyY = keyboardY + (y*btnSzH);
|
||||||
|
|
||||||
|
if(event.button.x < keyX) continue;
|
||||||
|
if(event.button.y < keyY) continue;
|
||||||
|
if(event.button.x >= (keyX + btnSzW)) continue;
|
||||||
|
if(event.button.y >= (keyY + btnSzH)) continue;
|
||||||
|
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
|
||||||
|
HandleKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_TEXTINPUT:
|
||||||
|
{
|
||||||
|
|
||||||
|
if(event.text.text[0] != ' ') {
|
||||||
|
Append(event.text.text[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
switch(event.key.keysym.scancode)
|
||||||
|
{
|
||||||
|
case SDL_SCANCODE_SPACE:
|
||||||
|
{
|
||||||
|
if(this->y == -1)
|
||||||
|
{
|
||||||
|
Append(' ');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_UP:
|
||||||
|
{
|
||||||
|
this->y--;
|
||||||
|
if(this->y < -1) this->y=-1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_DOWN:
|
||||||
|
{
|
||||||
|
this->y++;
|
||||||
|
if(this->y >= KEYBOARD_HEIGHT) this->y=KEYBOARD_HEIGHT-1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_LEFT:
|
||||||
|
{
|
||||||
|
if(this->y == -1)
|
||||||
|
{
|
||||||
|
this->cursor--;
|
||||||
|
if(this->cursor >= this->tb->text.size())
|
||||||
|
this->cursor=0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->x--;
|
||||||
|
if(this->x < 0) this->x=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_RIGHT:
|
||||||
|
{
|
||||||
|
if(this->y == -1)
|
||||||
|
{
|
||||||
|
this->cursor++;
|
||||||
|
if(this->cursor >= this->tb->text.size())
|
||||||
|
this->cursor=this->tb->text.size();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->x++;
|
||||||
|
if(this->x >= KEYBOARD_WIDTH) this->x=KEYBOARD_WIDTH-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_SCANCODE_RETURN:
|
||||||
|
case SDL_SCANCODE_RETURN2:
|
||||||
|
case SDL_SCANCODE_ESCAPE:
|
||||||
|
{
|
||||||
|
window->SetWidget(this->page);
|
||||||
|
if(this->tb)
|
||||||
|
window->SetCurrent(this->tb.get());
|
||||||
|
return EventResult::Handled;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_SCANCODE_BACKSPACE:
|
||||||
|
{
|
||||||
|
Append('\b');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return EventResult::Ignored;
|
||||||
|
}
|
||||||
|
void TextBox::TextBoxDialog::Draw(SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto window = this->GetRoot();
|
||||||
|
if(!window) return;
|
||||||
|
|
||||||
|
if(this->page)
|
||||||
|
this->page->Draw(rect);
|
||||||
|
|
||||||
|
int btnTextSzW=0;
|
||||||
|
int btnTextSzH=0;
|
||||||
|
|
||||||
|
auto font = window->GetFont();
|
||||||
|
font->CalculateSize("OO",btnTextSzW,btnTextSzH);
|
||||||
|
auto textWidth = font->MaxWidth();
|
||||||
|
int btnSzW = btnTextSzW+16;
|
||||||
|
int btnSzH = btnTextSzW+16;
|
||||||
|
|
||||||
|
int keyboardHeight = (KEYBOARD_HEIGHT * btnSzH) + 16;
|
||||||
|
int keyboardWidth = (KEYBOARD_WIDTH * btnSzW) + 16;
|
||||||
|
|
||||||
|
int keyboardX = ((rect.w/2) - (keyboardWidth/2))+8+rect.x;
|
||||||
|
int keyboardY = rect.y+8+(rect.h-keyboardHeight);
|
||||||
|
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), 0,0,0,200);
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &rect);
|
||||||
|
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_PRIMARY.r,COLOR_PRIMARY.g,COLOR_PRIMARY.b,COLOR_PRIMARY.a);
|
||||||
|
|
||||||
|
int height = font->MaxHeight()+16;
|
||||||
|
|
||||||
|
SDL_Rect r2 = {
|
||||||
|
.x = rect.x,
|
||||||
|
.y=((rect.h-keyboardHeight)/2) - (height/2),
|
||||||
|
.w = rect.w,
|
||||||
|
.h = height
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &r2);
|
||||||
|
|
||||||
|
auto maxChars = (rect.w-16) / textWidth;
|
||||||
|
|
||||||
|
|
||||||
|
if(tb->text.size() <= maxChars)
|
||||||
|
{
|
||||||
|
font->Render(window->GetRenderer(), rect.x+8, ((rect.h-keyboardHeight)/2) - (height/2) + 8, tb->text, COLOR_TEXT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto page = this->cursor / maxChars;
|
||||||
|
font->Render(window->GetRenderer(), rect.x+8,((rect.h-keyboardHeight)/2) - (height/2) + 8, tb->text.substr(page*maxChars,maxChars), COLOR_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cur = (int)(this->cursor % maxChars);
|
||||||
|
r2 = {.x=rect.x+8+(textWidth*cur),.y=((rect.h-keyboardHeight)/2) - (height/2)+ height-4,.w=textWidth,.h=4};
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_HIGHLIGHT.r,COLOR_HIGHLIGHT.g,COLOR_HIGHLIGHT.b,COLOR_HIGHLIGHT.a);
|
||||||
|
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &r2);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_PRIMARY.r,COLOR_PRIMARY.g,COLOR_PRIMARY.b,COLOR_PRIMARY.a);
|
||||||
|
|
||||||
|
r2 = {
|
||||||
|
.x = rect.x,
|
||||||
|
.y=(rect.h-keyboardHeight)+rect.y,
|
||||||
|
.w = rect.w,
|
||||||
|
.h = keyboardHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SDL_RenderFillRect(window->GetRenderer(), &r2);
|
||||||
|
|
||||||
|
|
||||||
|
for(int y=0;y<KEYBOARD_HEIGHT; y++)
|
||||||
|
{
|
||||||
|
for(int x = 0; x < KEYBOARD_WIDTH; x++)
|
||||||
|
{
|
||||||
|
int textX = (x*btnSzW) + keyboardX;
|
||||||
|
int textY = (y*btnSzH) + keyboardY;
|
||||||
|
|
||||||
|
font->Render(window->GetRenderer(), textX, textY, (shift ? upper : lower)[y][x], COLOR_TEXT);
|
||||||
|
|
||||||
|
if(this->x == x && this->y == y)
|
||||||
|
{
|
||||||
|
SDL_Rect r = {.x=textX-8,.y=textY-8,.w = btnSzW, .h=btnSzH};
|
||||||
|
SDL_SetRenderDrawColor(window->GetRenderer(), COLOR_HIGHLIGHT.r, COLOR_HIGHLIGHT.g,COLOR_HIGHLIGHT.b,COLOR_HIGHLIGHT.a);
|
||||||
|
window->DrawRectThick(r,6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user