mirror of
https://onedev.site.tesses.net/tesses-framework
synced 2026-03-26 08:00:27 +00:00
Add GUI Support
This commit is contained in:
@@ -10,7 +10,7 @@ namespace Tesses::Framework::Date
|
||||
{
|
||||
int GetTimeZone()
|
||||
{
|
||||
#if defined(__SWITCH__) || defined(_WIN32) || defined(GEKKO)
|
||||
#if defined(__SWITCH__) || defined(_WIN32) || defined(GEKKO) || defined(__PS2__)
|
||||
return (int)(-_timezone);
|
||||
#else
|
||||
return (int)(-timezone);
|
||||
@@ -18,7 +18,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
bool TimeZoneSupportDST()
|
||||
{
|
||||
#if defined(__SWITCH__) || defined(_WIN32) || defined(GEKKO)
|
||||
#if defined(__SWITCH__) || defined(_WIN32) || defined(GEKKO) || defined(__PS2__)
|
||||
return _daylight == 1;
|
||||
#else
|
||||
return daylight == 1;
|
||||
@@ -56,9 +56,9 @@ namespace Tesses::Framework::Date
|
||||
secs /= 60;
|
||||
hour = secs % 24;
|
||||
|
||||
day = (int)(uint32_t)ymd.day();
|
||||
month = (int)(uint32_t)ymd.month();
|
||||
year = (int32_t)ymd.year();
|
||||
day = (int)(unsigned)ymd.day();
|
||||
month = (int)(unsigned)ymd.month();
|
||||
year = (int)ymd.year();
|
||||
}
|
||||
DateTime::DateTime(int64_t epoch)
|
||||
{
|
||||
@@ -141,7 +141,7 @@ namespace Tesses::Framework::Date
|
||||
|
||||
date::year_month_day ymd(epoch);
|
||||
|
||||
auto month = (uint32_t)ymd.month();
|
||||
auto month = (unsigned)ymd.month();
|
||||
|
||||
if(month > 3 && month < 11)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
else if(month == 3)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
auto day = (unsigned)ymd.day();
|
||||
if(day > 14) isDST=true;
|
||||
else if(day >= 8 && day <= 14)
|
||||
{
|
||||
@@ -172,7 +172,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
else if(month == 11)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
auto day = (unsigned)ymd.day();
|
||||
if(day >= 1 && day <= 7)
|
||||
{
|
||||
date::year_month_weekday ymw(epoch);
|
||||
@@ -220,7 +220,7 @@ namespace Tesses::Framework::Date
|
||||
|
||||
date::year_month_day ymd(epoch);
|
||||
|
||||
auto month = (uint32_t)ymd.month();
|
||||
auto month = (unsigned)ymd.month();
|
||||
|
||||
if(month > 3 && month < 11)
|
||||
{
|
||||
@@ -228,7 +228,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
else if(month == 3)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
auto day = (unsigned)ymd.day();
|
||||
if(day > 14) isDST=true;
|
||||
else if(day >= 8 && day <= 14)
|
||||
{
|
||||
@@ -251,7 +251,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
else if(month == 11)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
auto day = (unsigned)ymd.day();
|
||||
if(day >= 1 && day <= 7)
|
||||
{
|
||||
date::year_month_weekday ymw(epoch);
|
||||
@@ -357,7 +357,7 @@ namespace Tesses::Framework::Date
|
||||
|
||||
date::year_month_day ymd(epoch);
|
||||
|
||||
auto month = (uint32_t)ymd.month();
|
||||
auto month = (unsigned)ymd.month();
|
||||
|
||||
if(month > 3 && month < 11)
|
||||
{
|
||||
@@ -365,7 +365,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
else if(month == 3)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
auto day = (unsigned)ymd.day();
|
||||
if(day > 14) isDST=true;
|
||||
else if(day >= 8 && day <= 14)
|
||||
{
|
||||
@@ -388,7 +388,7 @@ namespace Tesses::Framework::Date
|
||||
}
|
||||
else if(month == 11)
|
||||
{
|
||||
auto day = (uint32_t)ymd.day();
|
||||
auto day = (unsigned)ymd.day();
|
||||
if(day >= 1 && day <= 7)
|
||||
{
|
||||
date::year_month_weekday ymw(epoch);
|
||||
|
||||
@@ -36,7 +36,11 @@ namespace Tesses::Framework::Http
|
||||
p = p.substr(1, p.size()-2);
|
||||
}
|
||||
|
||||
|
||||
p = HttpUtils::UrlPathDecode(p);
|
||||
|
||||
|
||||
|
||||
cd.filename = p;
|
||||
}
|
||||
else if(res2[0] == "name")
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Tesses::Framework::Http
|
||||
if(this->allowListing)
|
||||
{
|
||||
std::string p = HttpUtils::HtmlEncode(ctx.originalPath);
|
||||
std::string html = "<!DOCTYPE html><html><head><title>Index of ";
|
||||
std::string html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>Index of ";
|
||||
html.append(p);
|
||||
html.append("</title></head><body><h1>Index of ");
|
||||
html.append(p);
|
||||
|
||||
@@ -9,19 +9,18 @@
|
||||
#include "TessesFramework/Crypto/MbedHelpers.hpp"
|
||||
#include "TessesFramework/Threading/Mutex.hpp"
|
||||
#include "TessesFramework/Common.hpp"
|
||||
#include "TessesFramework/TextStreams/StdIOWriter.hpp"
|
||||
|
||||
#include <iostream>
|
||||
using FileStream = Tesses::Framework::Streams::FileStream;
|
||||
using Stream = Tesses::Framework::Streams::Stream;
|
||||
using SeekOrigin = Tesses::Framework::Streams::SeekOrigin;
|
||||
using MemoryStream = Tesses::Framework::Streams::MemoryStream;
|
||||
using StreamReader = Tesses::Framework::TextStreams::StreamReader;
|
||||
using StreamWriter = Tesses::Framework::TextStreams::StreamWriter;
|
||||
using TcpServer = Tesses::Framework::Streams::TcpServer;
|
||||
using NetworkStream = Tesses::Framework::Streams::NetworkStream;
|
||||
using BufferedStream = Tesses::Framework::Streams::BufferedStream;
|
||||
|
||||
|
||||
using namespace Tesses::Framework::TextStreams;
|
||||
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
@@ -503,6 +502,7 @@ namespace Tesses::Framework::Http
|
||||
else
|
||||
{
|
||||
auto strm = cb(ct, cd1.filename, cd1.fieldName);
|
||||
if(strm == nullptr) strm = new Stream();
|
||||
bool retVal = parseUntillBoundaryEnd(&ctx->GetStream(),strm,boundary);
|
||||
delete strm;
|
||||
return retVal;
|
||||
@@ -635,13 +635,13 @@ namespace Tesses::Framework::Http
|
||||
{
|
||||
TF_LOG("Before printing interfaces");
|
||||
|
||||
std::cout << "\x1B[34mInterfaces:\n";
|
||||
StdOut() << "\x1B[34mInterfaces:" << NewLine();
|
||||
for(auto _ip : NetworkStream::GetIPs())
|
||||
{
|
||||
std::cout << "\x1B[32m";
|
||||
std::cout << _ip.first << ": ";
|
||||
std::cout << "\x1B[35mhttp://";
|
||||
std::cout << _ip.second << ":" << std::to_string(this->GetPort()) << "/\n";
|
||||
StdOut() << "\x1B[32m"
|
||||
<< _ip.first << ": "
|
||||
<< "\x1B[35mhttp://"
|
||||
<< _ip.second << ":" << (uint64_t)this->GetPort() << "/" << NewLine();
|
||||
}
|
||||
|
||||
|
||||
@@ -649,7 +649,7 @@ namespace Tesses::Framework::Http
|
||||
if(this->showARTL)
|
||||
{
|
||||
if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl;
|
||||
std::cout << "\x1B[31mAlmost Ready to Listen\x1B[39m\n";
|
||||
StdOut() << "\x1B[31mAlmost Ready to Listen\x1B[39m" << NewLine();
|
||||
}
|
||||
|
||||
TF_LOG("After printing interfaces");
|
||||
|
||||
@@ -516,6 +516,68 @@ namespace Tesses::Framework::Http {
|
||||
}
|
||||
return strs;
|
||||
}
|
||||
std::string HttpUtils::HtmlDecodeOnlyEntityNumber(std::string v)
|
||||
{
|
||||
std::string buff={};
|
||||
int state = 0;
|
||||
uint64_t n=0;
|
||||
for(auto item : v)
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case 0:
|
||||
if(item == '&') state=1;
|
||||
else buff.push_back(item);
|
||||
break;
|
||||
case 1:
|
||||
if(item == '#') {state = 2; n=0;}
|
||||
else {state=0; buff.push_back('&'); buff.push_back(item); }
|
||||
break;
|
||||
case 2:
|
||||
if(item == ';') {
|
||||
state = 0;
|
||||
if(n <= 0x7F)
|
||||
{
|
||||
buff.push_back((char)n);
|
||||
}
|
||||
else if(n >= 0x80 && n <= 0x7FF)
|
||||
{
|
||||
uint8_t high = 0b11000000 | ((uint8_t)(n >> 6) & 0b00011111);
|
||||
uint8_t low = 0b10000000 | ((uint8_t)(n) & 0b00111111);
|
||||
buff.push_back((char)high);
|
||||
buff.push_back((char)low);
|
||||
}
|
||||
else if(n >= 0x800 && n <= 0xFFFF)
|
||||
{
|
||||
uint8_t high = 0b11100000 | ((uint8_t)(n >> 12) & 0b00001111);
|
||||
uint8_t low = 0b10000000 | ((uint8_t)(n >> 6) & 0b00111111);
|
||||
uint8_t lowest = 0b10000000 | ((uint8_t)(n) & 0b00111111);
|
||||
buff.push_back((char)high);
|
||||
buff.push_back((char)low);
|
||||
buff.push_back((char)lowest);
|
||||
}
|
||||
else if(n >= 0x010000 && n <= 0x10FFFF)
|
||||
{
|
||||
uint8_t highest = 0b11110000 | ((uint8_t)(n >> 18) & 0b00000111);
|
||||
uint8_t high = 0b10000000 | ((uint8_t)(n >> 12) & 0b00111111);
|
||||
uint8_t low = 0b10000000 | ((uint8_t)(n >> 6) & 0b00111111);
|
||||
uint8_t lowest = 0b10000000 | ((uint8_t)(n) & 0b00111111);
|
||||
buff.push_back((char)highest);
|
||||
|
||||
buff.push_back((char)high);
|
||||
buff.push_back((char)low);
|
||||
buff.push_back((char)lowest);
|
||||
}
|
||||
}
|
||||
else if(item >= '0' && item <= '9')
|
||||
{
|
||||
n *= 10;
|
||||
n += item - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
std::string HttpUtils::HtmlEncode(std::string html)
|
||||
{
|
||||
std::string myHtml = {};
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/FontCache.hpp"
|
||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||
#include "TessesFramework/TanoheSans-Regular.h"
|
||||
using HU= Tesses::Framework::Http::HttpUtils;
|
||||
namespace Tesses::Framework::SDL2 {
|
||||
void FontCache::Load(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& color)
|
||||
void FontCache::Load(SDL_Renderer* renderer,TTF_Font* font)
|
||||
{
|
||||
this->mw=0;
|
||||
this->mh=0;
|
||||
@@ -9,7 +12,7 @@ void FontCache::Load(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& colo
|
||||
|
||||
for(size_t i = 0; i < this->font_chrs.size();i++)
|
||||
{
|
||||
SDL_Surface* surf = TTF_RenderGlyph_Blended(font,(Uint16)(i+32),color);
|
||||
SDL_Surface* surf = TTF_RenderGlyph_Blended(font,(Uint16)(i+32),{.r=255,.g=255,.b=255,.a=255});
|
||||
if(surf->w > this->mw) mw = surf->w;
|
||||
if(surf->h > this->mh) mh = surf->h;
|
||||
this->font_chrs[i] = SDL_CreateTextureFromSurface(renderer,surf);
|
||||
@@ -17,35 +20,123 @@ void FontCache::Load(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& colo
|
||||
|
||||
}
|
||||
}
|
||||
FontCache::FontCache(SDL_Renderer* renderer,std::string font,int sz,const SDL_Color& color)
|
||||
FontCache::FontCache(SDL_Renderer* renderer,std::string font,int sz)
|
||||
{
|
||||
TTF_Font* f = TTF_OpenFont(font.c_str(),sz);
|
||||
Load(renderer,f,color);
|
||||
Load(renderer,f);
|
||||
TTF_CloseFont(f);
|
||||
}
|
||||
FontCache::FontCache(SDL_Renderer* renderer,const uint8_t* mem,size_t cnt,int sz,const SDL_Color& color)
|
||||
FontCache::FontCache(SDL_Renderer* renderer,const uint8_t* mem,size_t cnt,int sz)
|
||||
{
|
||||
|
||||
TTF_Font* f = TTF_OpenFontRW(SDL_RWFromConstMem(mem,cnt),1,sz);
|
||||
Load(renderer,f,color);
|
||||
Load(renderer,f);
|
||||
TTF_CloseFont(f);
|
||||
}
|
||||
FontCache::FontCache(SDL_Renderer* renderer,const std::vector<uint8_t>& v,int sz,const SDL_Color& color) : FontCache(renderer,v.data(),v.size(),sz,color)
|
||||
FontCache::FontCache(SDL_Renderer* renderer,const std::vector<uint8_t>& v,int sz) : FontCache(renderer,v.data(),v.size(),sz)
|
||||
{
|
||||
|
||||
}
|
||||
FontCache::FontCache(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& color)
|
||||
FontCache::FontCache(SDL_Renderer* renderer,TTF_Font* font)
|
||||
{
|
||||
this->Load(renderer,font,color);
|
||||
this->Load(renderer,font);
|
||||
}
|
||||
FontCache::FontCache(SDL_Renderer* renderer,int sz) : FontCache(renderer,TANOHESANSREGULAR,TANOHESANSREGULAR_SIZE,sz)
|
||||
{
|
||||
|
||||
}
|
||||
void FontCache::CalculateSize(std::string text, int& x,int& y)
|
||||
{
|
||||
int myX = 0;
|
||||
x=0;
|
||||
y=0;
|
||||
int maxH = MaxHeight();
|
||||
y=maxH;
|
||||
for(auto c : text)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\n':
|
||||
{
|
||||
y += maxH;
|
||||
if(myX > x) x = myX;
|
||||
myX = 0;
|
||||
}
|
||||
break;
|
||||
case '\t':
|
||||
{
|
||||
auto tex = operator[](' ');
|
||||
int wi;
|
||||
SDL_QueryTexture(tex,NULL,NULL,&wi,NULL);
|
||||
|
||||
myX += wi * 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
auto tex = operator[](c);
|
||||
int wi;
|
||||
int he;
|
||||
SDL_QueryTexture(tex,NULL,NULL,&wi,&he);
|
||||
|
||||
myX += wi;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if(myX > x) x = myX;
|
||||
}
|
||||
void FontCache::Render(SDL_Renderer* renderer,int x,int y, std::string text,const SDL_Color& color)
|
||||
{
|
||||
int myX = x;
|
||||
int maxH = MaxHeight();
|
||||
for(auto c : text)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\n':
|
||||
{
|
||||
y += maxH;
|
||||
myX = x;
|
||||
}
|
||||
break;
|
||||
case '\t':
|
||||
{
|
||||
auto tex = GetCharOfColor(' ',color);
|
||||
int wi;
|
||||
SDL_QueryTexture(tex,NULL,NULL,&wi,NULL);
|
||||
|
||||
myX += wi * 4;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
auto tex = GetCharOfColor(c,color);
|
||||
int wi;
|
||||
int he;
|
||||
SDL_QueryTexture(tex,NULL,NULL,&wi,&he);
|
||||
SDL_Rect src={.x=0,.y=0,.w=wi,.h=he};
|
||||
|
||||
SDL_Rect dest={.x=myX,.y=y,.w=wi,.h=he};
|
||||
|
||||
myX += wi;
|
||||
SDL_RenderCopy(renderer,tex,&src,&dest);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_Texture* FontCache::GetCharOfColor(char c, const SDL_Color& color)
|
||||
{
|
||||
auto res = (c >= 32 && c <= 126) ? this->font_chrs[c-32] : this->font_chrs[95];
|
||||
SDL_SetTextureColorMod(res,color.r,color.g,color.b);
|
||||
return res;
|
||||
}
|
||||
SDL_Texture* FontCache::operator[](char c)
|
||||
{
|
||||
if(c >= 32 && c <= 126)
|
||||
{
|
||||
return this->font_chrs[c-32];
|
||||
}
|
||||
return this->font_chrs[95];
|
||||
return GetCharOfColor(c,{.r=255,.g=255,.b=255,.a=255});
|
||||
}
|
||||
FontCache::~FontCache()
|
||||
{
|
||||
@@ -65,5 +156,121 @@ int FontCache::PointSize()
|
||||
{
|
||||
return this->ps;
|
||||
}
|
||||
|
||||
bool TryParseSDLColor(std::string str, SDL_Color& col)
|
||||
{
|
||||
str = HU::Replace(str," ","");
|
||||
//rgba(255,255,255,1.0)
|
||||
//rgb(197, 30, 30)
|
||||
//#rgb
|
||||
//#rgba
|
||||
//#rrggbb
|
||||
//#rrggbbaa
|
||||
|
||||
if(str.size() >= 4 && str[0] == '#')
|
||||
{
|
||||
if(str.size() == 4)
|
||||
{
|
||||
auto r = HU::HexToNibble(str[1]);
|
||||
r |= r << 4;
|
||||
auto g = HU::HexToNibble(str[2]);
|
||||
g |= g << 4;
|
||||
auto b = HU::HexToNibble(str[3]);
|
||||
b |= b << 4;
|
||||
col.r = r;
|
||||
col.g = g;
|
||||
col.b = b;
|
||||
col.a = 255;
|
||||
return true;
|
||||
}
|
||||
else if(str.size() == 5)
|
||||
{
|
||||
auto r = HU::HexToNibble(str[1]);
|
||||
r |= r << 4;
|
||||
auto g = HU::HexToNibble(str[2]);
|
||||
g |= g << 4;
|
||||
auto b = HU::HexToNibble(str[3]);
|
||||
b |= b << 4;
|
||||
auto a = HU::HexToNibble(str[4]);
|
||||
a |= a << 4;
|
||||
col.r = r;
|
||||
col.g = g;
|
||||
col.b = b;
|
||||
col.a = a;
|
||||
return true;
|
||||
}
|
||||
else if(str.size() == 7) {
|
||||
auto r = HU::HexToNibble(str[1]);
|
||||
r |= HU::HexToNibble(str[2]) << 4;
|
||||
auto g = HU::HexToNibble(str[3]);
|
||||
g |= HU::HexToNibble(str[4]) << 4;
|
||||
auto b = HU::HexToNibble(str[5]);
|
||||
b |= HU::HexToNibble(str[6]) << 4;
|
||||
|
||||
col.r = r;
|
||||
col.g = g;
|
||||
col.b = b;
|
||||
col.a = 255;
|
||||
return true;
|
||||
}
|
||||
else if(str.size() == 9)
|
||||
{
|
||||
auto r = HU::HexToNibble(str[1]);
|
||||
r |= HU::HexToNibble(str[2]) << 4;
|
||||
auto g = HU::HexToNibble(str[3]);
|
||||
g |= HU::HexToNibble(str[4]) << 4;
|
||||
auto b = HU::HexToNibble(str[5]);
|
||||
b |= HU::HexToNibble(str[6]) << 4;
|
||||
auto a = HU::HexToNibble(str[7]);
|
||||
a |= HU::HexToNibble(str[8]) << 4;
|
||||
|
||||
col.r = r;
|
||||
col.g = g;
|
||||
col.b = b;
|
||||
col.a = a;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if(str.size() > 4 && strncmp(str.c_str(),"rgb(",4) == 0 && str[str.size()-1] == ')')
|
||||
{
|
||||
str = HU::Replace(str.substr(4),")","");
|
||||
auto parts = HU::SplitString(str,",");
|
||||
if(parts.size() != 3) return false;
|
||||
try{
|
||||
auto r = std::stoul(parts[0]);
|
||||
auto g = std::stoul(parts[1]);
|
||||
auto b = std::stoul(parts[2]);
|
||||
col.r = (Uint8)r;
|
||||
col.g = (Uint8)g;
|
||||
col.b = (Uint8)b;
|
||||
col.a = 255;
|
||||
} catch(...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(str.size() > 5 && strncmp(str.c_str(),"rgba(",5) == 0 && str[str.size()-1] == ')')
|
||||
{
|
||||
str = HU::Replace(str.substr(5),")","");
|
||||
auto parts = HU::SplitString(str,",");
|
||||
if(parts.size() != 4) return false;
|
||||
try{
|
||||
auto r = std::stoul(parts[0]);
|
||||
auto g = std::stoul(parts[1]);
|
||||
auto b = std::stoul(parts[2]);
|
||||
double a= std::stod(parts[3]);
|
||||
col.r = (Uint8)r;
|
||||
col.g = (Uint8)g;
|
||||
col.b = (Uint8)b;
|
||||
col.a = (Uint8)(a * 255);
|
||||
} catch(...) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
231
src/SDL2/GUI.cpp
Normal file
231
src/SDL2/GUI.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/GUI.hpp"
|
||||
#include <iostream>
|
||||
namespace Tesses::Framework::SDL2
|
||||
{
|
||||
GUI gui;
|
||||
void GUI::Update()
|
||||
{
|
||||
if(this->windows.empty()) return;
|
||||
for(auto index = this->windows.begin(); index != this->windows.end(); index++)
|
||||
{
|
||||
if(*index == nullptr)
|
||||
{
|
||||
this->windows.erase(index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
if(this->windows.empty()) return;
|
||||
|
||||
|
||||
SDL_Event event;
|
||||
while(SDL_PollEvent(&event))
|
||||
{
|
||||
|
||||
for(auto win : this->windows)
|
||||
{
|
||||
if(win == nullptr) continue;
|
||||
auto id = SDL_GetWindowID(win->window);
|
||||
switch(event.type)
|
||||
{
|
||||
case SDL_EventType::SDL_WINDOWEVENT:
|
||||
if(event.window.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_EventType::SDL_MOUSEBUTTONUP:
|
||||
if(event.button.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_MOUSEMOTION:
|
||||
if(event.motion.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_MOUSEWHEEL:
|
||||
if(event.wheel.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_KEYUP:
|
||||
case SDL_EventType::SDL_KEYDOWN:
|
||||
if(event.key.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_TEXTEDITING:
|
||||
if(event.edit.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_TEXTEDITING_EXT:
|
||||
if(event.editExt.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_TEXTINPUT:
|
||||
if(event.text.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_DROPBEGIN:
|
||||
case SDL_EventType::SDL_DROPCOMPLETE:
|
||||
case SDL_EventType::SDL_DROPFILE:
|
||||
case SDL_EventType::SDL_DROPTEXT:
|
||||
if(event.drop.windowID == id)
|
||||
{
|
||||
win->Event(event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
win->Event(event);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(event.type == SDL_QUIT)
|
||||
{
|
||||
TF_SetIsRunning(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(auto item : this->windows)
|
||||
{
|
||||
if(item != nullptr)
|
||||
item->Draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Clipper::Clipper(SDL_Renderer* renderer, SDL_Rect& myRect)
|
||||
{
|
||||
this->isClipped=SDL_RenderIsClipEnabled(renderer);
|
||||
SDL_RenderGetClipRect(renderer,&this->theRect);
|
||||
if(!this->isClipped) this->theRect = myRect;
|
||||
this->renderer = renderer;
|
||||
}
|
||||
void Clipper::ClipRect(SDL_Rect& child, SDL_Rect& parent)
|
||||
{
|
||||
if(child.x < parent.x)
|
||||
{
|
||||
int rem = parent.x- child.x;
|
||||
child.x += rem;
|
||||
child.w -= rem;
|
||||
}
|
||||
if(child.y < parent.y)
|
||||
{
|
||||
int rem = parent.y- child.y;
|
||||
child.y += rem;
|
||||
child.h -= rem;
|
||||
}
|
||||
|
||||
if((child.x + child.w) > (parent.x + parent.w))
|
||||
child.w = (parent.x + parent.w) - child.x;
|
||||
|
||||
if((child.y + child.h) > (parent.y + parent.h))
|
||||
child.h = (parent.y + parent.h) - child.y;
|
||||
|
||||
}
|
||||
bool Clipper::Clip(SDL_Rect rect)
|
||||
{
|
||||
ClipRect(rect,this->theRect);
|
||||
if(rect.w <= 0 || rect.h <= 0) return false;
|
||||
|
||||
SDL_RenderSetClipRect(renderer, &rect);
|
||||
return true;
|
||||
}
|
||||
Clipper::~Clipper()
|
||||
{
|
||||
if(isClipped) SDL_RenderSetClipRect(renderer, &this->theRect);
|
||||
else SDL_RenderSetClipRect(renderer, nullptr);
|
||||
}
|
||||
|
||||
GUIPalette::GUIPalette()
|
||||
{
|
||||
this->fontSize=24;
|
||||
}
|
||||
SDL_Color& GUIPalette::GetBorderColor(bool isHovering, bool isActive, bool isMouseDown)
|
||||
{
|
||||
bool isHovering2=isHovering ^ isMouseDown;
|
||||
if(isHovering2 && isActive)
|
||||
return this->border_hover_active;
|
||||
if(isHovering2)
|
||||
return this->border_hover;
|
||||
if(isActive)
|
||||
return this->border_active;
|
||||
return this->border_color;
|
||||
}
|
||||
|
||||
GUIPalette::GUIPalette(SDL_Color accent, SDL_Color background, SDL_Color border_color, SDL_Color border_hover, SDL_Color border_active, SDL_Color border_hover_active, int fontSize)
|
||||
{
|
||||
this->accent=accent;
|
||||
this->background = background;
|
||||
this->border_color=border_color;
|
||||
this->border_hover = border_hover;
|
||||
this->border_active = border_active;
|
||||
this->border_hover_active=border_hover_active;
|
||||
this->fontSize = fontSize;
|
||||
}
|
||||
|
||||
std::string GUIEventArgs::Type()
|
||||
{
|
||||
return "Base";
|
||||
}
|
||||
GUIEventArgs::~GUIEventArgs()
|
||||
{
|
||||
|
||||
}
|
||||
std::string GUIMouseButtonEventArgs::Type()
|
||||
{
|
||||
return "MouseButton";
|
||||
}
|
||||
std::string GUIJsonViewNotFoundEventArgs::Type()
|
||||
{
|
||||
return "JsonViewNotFound";
|
||||
}
|
||||
std::string GUISDLEventEventArgs::Type()
|
||||
{
|
||||
return "SDLEvent";
|
||||
}
|
||||
|
||||
GUIPalette::GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize)
|
||||
{
|
||||
this->accent = accent;
|
||||
this->fontSize = fontSize;
|
||||
|
||||
if(isDarkMode)
|
||||
{
|
||||
this->background = {.r = 42,.g=42,.b=42,.a=255};
|
||||
this->border_color = {.r=0,.g=0,.b=0,.a=255};
|
||||
this->border_hover = {.r=92,.g=92,.b=92,.a=255};
|
||||
|
||||
this->border_active = {.r=200,.g=200,.b=200,.a=255};
|
||||
this->border_hover_active = {.r=(uint8_t)(255-accent.r),.g=(uint8_t)(255-accent.g),.b=(uint8_t)(255-accent.b),.a=255};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this->background = {.r=239,.g=239,.b=239,.a=255};
|
||||
this->border_color = {.r=0,.g=0,.b=0,.a=255};
|
||||
|
||||
this->border_active = {.r=92,.g=92,.b=92,.a=255};
|
||||
|
||||
this->border_hover = {.r=200,.g=200,.b=200,.a=255};
|
||||
|
||||
this->border_hover_active = {.r=(uint8_t)(255-accent.r),.g=(uint8_t)(255-accent.g),.b=(uint8_t)(255-accent.b),.a=255};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
367
src/SDL2/GUIWindow.cpp
Normal file
367
src/SDL2/GUIWindow.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/GUI.hpp"
|
||||
#include "TessesFramework/aardvark-fixed-regular.h"
|
||||
#include "TessesFramework/SDL2/Views/ButtonView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/LabelView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/CheckView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/ProgressView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/TextListView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
|
||||
#include "TessesFramework/SDL2/ParseColor.hpp"
|
||||
namespace Tesses::Framework::SDL2
|
||||
{
|
||||
void GUIWindow::MakeActive(View* view)
|
||||
{
|
||||
if(!view->GetViewFlag(VIEWFLAG_TABSTOP)) return;
|
||||
if(view->GetViewFlag(VIEWFLAG_ISACTIVE)) return;
|
||||
DeactivateAll(this);
|
||||
view->SetViewFlag(VIEWFLAG_ISACTIVE,true);
|
||||
}
|
||||
void GUIWindow::DeactivateAll(View* view)
|
||||
{
|
||||
view->SetViewFlag(VIEWFLAG_ISACTIVE,false);
|
||||
auto cv = dynamic_cast<ContainerView*>(view);
|
||||
if(cv != nullptr)
|
||||
{
|
||||
for(size_t i = 0; i < cv->ViewCount();i++)
|
||||
{
|
||||
DeactivateAll(cv->GetViewAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
void GUIWindow::TabNext(View* view,TabNextResult& nr)
|
||||
{
|
||||
if(nr == TabNextResult::Done)
|
||||
return;
|
||||
auto cv = dynamic_cast<ContainerView*>(view);
|
||||
if(cv != nullptr)
|
||||
{
|
||||
for(size_t i = 0; i < cv->ViewCount();i++)
|
||||
{
|
||||
TabNext(cv->GetViewAt(i),nr);
|
||||
if(nr == TabNextResult::Done)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(view->GetViewFlag(VIEWFLAG_ISACTIVE))
|
||||
{
|
||||
if(view->GetViewFlag(VIEWFLAG_INTERCEPT_TAB))
|
||||
{
|
||||
SDL_Rect r;
|
||||
r.x=0;
|
||||
r.y=0;
|
||||
r.w=0;
|
||||
r.h=0;
|
||||
SDL_Event event;
|
||||
event.type = SDL_KEYDOWN;
|
||||
event.key.keysym.mod = SDL_Keymod::KMOD_NONE;
|
||||
event.key.keysym.scancode = SDL_SCANCODE_TAB;
|
||||
event.key.keysym.sym = SDL_KeyCode::SDLK_TAB;
|
||||
view->CallOnEvent(view,event,r,r);
|
||||
nr = TabNextResult::Done;
|
||||
}
|
||||
view->SetViewFlag(VIEWFLAG_ISACTIVE,false);
|
||||
nr= TabNextResult::TabNext;
|
||||
}
|
||||
else if(view->GetViewFlag(VIEWFLAG_TABSTOP) && nr == TabNextResult::TabNext)
|
||||
{
|
||||
view->SetViewFlag(VIEWFLAG_ISACTIVE,true);
|
||||
nr = TabNextResult::Done;
|
||||
}
|
||||
}
|
||||
}
|
||||
void GUIWindow::TabNext()
|
||||
{
|
||||
TabNextResult nr=TabNextResult::KeepGoing;
|
||||
TabNext(this,nr);
|
||||
if(nr != TabNextResult::Done)
|
||||
{
|
||||
nr = TabNextResult::TabNext;
|
||||
TabNext(this,nr);
|
||||
}
|
||||
}
|
||||
|
||||
void GUIWindow::SetView(View* view,bool owns)
|
||||
{
|
||||
if(this->ownsChild && this->child != view)
|
||||
delete this->child;
|
||||
this->child = view;
|
||||
this->ownsChild = owns;
|
||||
if(view != nullptr)
|
||||
view->parent = this;
|
||||
}
|
||||
GUIWindow* GUIWindow::GetWindow()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
size_t GUIWindow::ViewCount()
|
||||
{
|
||||
return this->child != nullptr ? 1 : 0;
|
||||
}
|
||||
View* GUIWindow::GetViewAt(size_t index)
|
||||
{
|
||||
if(index > 0) return nullptr;
|
||||
return this->child;
|
||||
}
|
||||
void GUIWindow::Draw()
|
||||
{
|
||||
int w,h;
|
||||
SDL_GetWindowSize(window,&w,&h);
|
||||
SDL_Rect r={.x=0,.y=0,.w=w,.h=h};
|
||||
OnDraw(renderer,r);
|
||||
}
|
||||
void GUIWindow::Event(SDL_Event& event)
|
||||
{
|
||||
int w,h;
|
||||
SDL_GetWindowSize(window,&w,&h);
|
||||
SDL_Rect r={.x=0,.y=0,.w=w,.h=h};
|
||||
OnEvent(event,r,r);
|
||||
}
|
||||
void GUIWindow::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer,this->palette.background.r,this->palette.background.g,this->palette.background.b,this->palette.background.a);
|
||||
SDL_RenderClear(renderer);
|
||||
if(this->child != nullptr)
|
||||
this->child->OnDraw(renderer,r);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
bool GUIWindow::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
||||
{
|
||||
|
||||
if(event.type == SDL_EventType::SDL_KEYDOWN && event.key.keysym.sym ==SDL_KeyCode::SDLK_TAB)
|
||||
{
|
||||
GUISDLEventEventArgs sdle;
|
||||
sdle.event = event;
|
||||
this->SDLEvent.Invoke(this,sdle);
|
||||
TabNext();
|
||||
return true;
|
||||
}
|
||||
if(this->child != nullptr) { GUISDLEventEventArgs sdle;
|
||||
sdle.event = event; this->SDLEvent.Invoke(this,sdle); return this->child->OnEvent(event,myBounds,myVisibleBounds);}
|
||||
return View::OnEvent(event,myBounds,myVisibleBounds);
|
||||
}
|
||||
GUIWindow::GUIWindow(std::string title, int w, int h, Uint32 flags, const GUIPalette& palette) : ContainerView(title)
|
||||
{
|
||||
this->window = SDL_CreateWindow(title.c_str(),SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,w,h,flags);
|
||||
this->renderer = SDL_CreateRenderer(this->window,-1,SDL_RENDERER_ACCELERATED);
|
||||
SDL_SetRenderDrawBlendMode(renderer,SDL_BlendMode::SDL_BLENDMODE_BLEND);
|
||||
this->child=nullptr;
|
||||
this->parent=nullptr;
|
||||
this->ownsChild=false;
|
||||
this->normal_font=nullptr;
|
||||
this->monospaced_font=nullptr;
|
||||
gui.windows.push_back(this);
|
||||
this->SetPalette(palette);
|
||||
}
|
||||
void GUIWindow::SetText(std::string text)
|
||||
{
|
||||
this->text = text;
|
||||
SDL_SetWindowTitle(this->window,text.c_str());
|
||||
}
|
||||
|
||||
void GUIWindow::SetPalette(const GUIPalette& palette)
|
||||
{
|
||||
this->palette = palette;
|
||||
if(this->normal_font != nullptr)
|
||||
delete this->normal_font;
|
||||
if(this->monospaced_font != nullptr)
|
||||
delete this->monospaced_font;
|
||||
this->normal_font = new FontCache(this->renderer,this->palette.fontSize);
|
||||
this->monospaced_font = new FontCache(this->renderer,AARDVARKFIXEDREGULAR,AARDVARKFIXEDREGULAR_SIZE,this->palette.fontSize);
|
||||
}
|
||||
|
||||
GUIWindow::~GUIWindow()
|
||||
{
|
||||
if(this->ownsChild)
|
||||
delete this->child;
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
|
||||
for(auto index = gui.windows.begin(); index < gui.windows.end(); index++)
|
||||
{
|
||||
if(*index == this)
|
||||
{
|
||||
*index = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void GUIWindow::SetView(Tesses::Framework::Serialization::Json::JToken item)
|
||||
{
|
||||
Tesses::Framework::Serialization::Json::JObject dict;
|
||||
if(Tesses::Framework::Serialization::Json::TryGetJToken(item,dict))
|
||||
{
|
||||
Tesses::Framework::Serialization::Json::JObject o;
|
||||
Tesses::Framework::Serialization::Json::JObject sz;
|
||||
Tesses::Framework::Serialization::Json::JObject pal0;
|
||||
std::string title;
|
||||
if(dict.TryGetValueAsType("Child",o))
|
||||
{
|
||||
this->SetView(CreateViewFromJson(o));
|
||||
}
|
||||
if(dict.TryGetValueAsType("Size",sz))
|
||||
{
|
||||
int w0,h0;
|
||||
|
||||
|
||||
SDL_GetWindowSize(this->window,&w0,&h0);
|
||||
int64_t w=w0;
|
||||
int64_t h=h0;
|
||||
|
||||
sz.TryGetValueAsType("Width",w);
|
||||
sz.TryGetValueAsType("Height",h);
|
||||
|
||||
SDL_SetWindowSize(this->window,(int)w,(int)h);
|
||||
}
|
||||
if(dict.TryGetValueAsType("Palette",pal0))
|
||||
{
|
||||
bool darkMode=true;
|
||||
SDL_Color accent={.r=255,.g=0,.b=0,.a=255};
|
||||
std::string _str;
|
||||
int64_t fontSize=20;
|
||||
|
||||
pal0.TryGetValueAsType("IsDarkMode",darkMode);
|
||||
pal0.TryGetValueAsType("FontSize",fontSize);
|
||||
if(pal0.TryGetValueAsType("Accent",_str))
|
||||
TryParseSDLColor(_str,accent);
|
||||
|
||||
GUIPalette pal(darkMode,accent,fontSize);
|
||||
if(pal0.TryGetValueAsType("Background",_str))
|
||||
TryParseSDLColor(_str,pal.background);
|
||||
if(pal0.TryGetValueAsType("Border",_str))
|
||||
TryParseSDLColor(_str,pal.border_color);
|
||||
if(pal0.TryGetValueAsType("BorderActive",_str))
|
||||
TryParseSDLColor(_str,pal.border_active);
|
||||
if(pal0.TryGetValueAsType("BorderHover",_str))
|
||||
TryParseSDLColor(_str,pal.border_hover);
|
||||
if(pal0.TryGetValueAsType("BorderHoverActive",_str))
|
||||
TryParseSDLColor(_str,pal.border_hover_active);
|
||||
this->SetPalette(pal);
|
||||
}
|
||||
if(dict.TryGetValueAsType("Title",title) || dict.TryGetValueAsType("Text",title))
|
||||
{
|
||||
this->SetText(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View* GUIWindow::CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json)
|
||||
{
|
||||
std::string type;
|
||||
if(json.TryGetValueAsType("Type",type))
|
||||
{
|
||||
std::string id={};
|
||||
std::string text={};
|
||||
bool active=false;
|
||||
json.TryGetValueAsType("Id",id);
|
||||
json.TryGetValueAsType("Text",text);
|
||||
json.TryGetValueAsType("Active",active);
|
||||
if(type == "ButtonView")
|
||||
{
|
||||
auto btn = new Views::ButtonView(text);
|
||||
btn->SetId(id);
|
||||
btn->SetViewFlag(VIEWFLAG_ISACTIVE,active);
|
||||
return btn;
|
||||
}
|
||||
else if(type == "CheckView")
|
||||
{
|
||||
bool checked;
|
||||
json.TryGetValueAsType("Checked",checked);
|
||||
auto cv = new Views::CheckView(checked,text);
|
||||
cv->SetId(id);
|
||||
|
||||
cv->SetViewFlag(VIEWFLAG_ISACTIVE,active);
|
||||
return cv;
|
||||
}
|
||||
else if(type == "LabelView")
|
||||
{
|
||||
auto lv = new Views::LabelView(text);
|
||||
lv->SetId(id);
|
||||
return lv;
|
||||
}
|
||||
else if(type == "ProgressView")
|
||||
{
|
||||
double v=0;
|
||||
json.TryGetValueAsType("Value",v);
|
||||
auto pv = new Views::ProgressView(v);
|
||||
pv->SetId(id);
|
||||
return pv;
|
||||
}
|
||||
else if(type == "TextListView")
|
||||
{
|
||||
std::vector<std::string> items;
|
||||
Tesses::Framework::Serialization::Json::JArray arr;
|
||||
if(json.TryGetValueAsType("Items",arr))
|
||||
{
|
||||
std::string str;
|
||||
for(auto item : arr)
|
||||
{
|
||||
if(Tesses::Framework::Serialization::Json::TryGetJToken(item,str)) items.push_back(str);
|
||||
}
|
||||
}
|
||||
int64_t index=-1;
|
||||
int64_t first=0;
|
||||
json.TryGetValueAsType("SelectedIndex",index);
|
||||
json.TryGetValueAsType("FirstIndex",first);
|
||||
|
||||
auto tlv = new Views::TextListView();
|
||||
|
||||
tlv->SetViewFlag(VIEWFLAG_ISACTIVE,active);
|
||||
tlv->SetId(id);
|
||||
tlv->items = items;
|
||||
tlv->firstIndex = (size_t)first;
|
||||
tlv->selected = (int)index;
|
||||
return tlv;
|
||||
}
|
||||
else if(type == "AbsoluteView")
|
||||
{
|
||||
auto av = new Views::AbsoluteView();
|
||||
av->SetId(id);
|
||||
Tesses::Framework::Serialization::Json::JArray arr;
|
||||
if(json.TryGetValueAsType("Items",arr))
|
||||
{
|
||||
for(auto item : arr)
|
||||
{
|
||||
Tesses::Framework::Serialization::Json::JObject dict;
|
||||
if(Tesses::Framework::Serialization::Json::TryGetJToken(item,dict))
|
||||
{
|
||||
Tesses::Framework::Serialization::Json::JObject boundsDict;
|
||||
SDL_Rect r={.x=0,.y=0,.w=200,.h=200};
|
||||
|
||||
if(dict.TryGetValueAsType("Bounds",boundsDict))
|
||||
{
|
||||
int64_t n;
|
||||
if(boundsDict.TryGetValueAsType("X",n)) r.x = (int)n;
|
||||
if(boundsDict.TryGetValueAsType("Y",n)) r.y = (int)n;
|
||||
if(boundsDict.TryGetValueAsType("Width",n)) r.w = (int)n;
|
||||
if(boundsDict.TryGetValueAsType("Height",n)) r.h = (int)n;
|
||||
}
|
||||
|
||||
auto myO = CreateViewFromJson(dict);
|
||||
if(myO != nullptr)
|
||||
{
|
||||
av->Add(r,myO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return av;
|
||||
}
|
||||
else {
|
||||
GUIJsonViewNotFoundEventArgs e;
|
||||
e.destView == nullptr;
|
||||
e.jsonObject = json;
|
||||
e.typeString = type;
|
||||
|
||||
JsonViewNotFound.Invoke(this,e);
|
||||
|
||||
return e.destView;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
77
src/SDL2/Stream.cpp
Normal file
77
src/SDL2/Stream.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
|
||||
#include "TessesFramework/SDL2/Stream.hpp"
|
||||
namespace Tesses::Framework::SDL2 {
|
||||
|
||||
static SDLCALL size_t rwops_stream_read(struct SDL_RWops * context, void *ptr,
|
||||
size_t size, size_t maxnum)
|
||||
{
|
||||
if(context->hidden.unknown.data1 == nullptr) return 0;
|
||||
auto ctx = static_cast<Tesses::Framework::Streams::Stream*>(context->hidden.unknown.data1);
|
||||
if(ctx->CanRead())
|
||||
return ctx->Read((uint8_t*)ptr,size*maxnum) / size;
|
||||
return 0;
|
||||
}
|
||||
static SDLCALL size_t rwops_stream_write(struct SDL_RWops * context, const void *ptr,
|
||||
size_t size, size_t maxnum)
|
||||
{
|
||||
if(context->hidden.unknown.data1 == nullptr) return 0;
|
||||
auto ctx = static_cast<Tesses::Framework::Streams::Stream*>(context->hidden.unknown.data1);
|
||||
if(ctx->CanWrite())
|
||||
return ctx->Write((const uint8_t*)ptr,size*maxnum) / size;
|
||||
return 0;
|
||||
}
|
||||
static SDLCALL Sint64 rwops_stream_seek(struct SDL_RWops * context, Sint64 offset,
|
||||
int whence)
|
||||
{
|
||||
|
||||
if(context->hidden.unknown.data1 == nullptr) return -1;
|
||||
auto ctx = static_cast<Tesses::Framework::Streams::Stream*>(context->hidden.unknown.data1);
|
||||
if(!ctx->CanSeek()) return -1;
|
||||
|
||||
switch(whence)
|
||||
{
|
||||
case RW_SEEK_SET:
|
||||
ctx->Seek(offset,Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||
break;
|
||||
case RW_SEEK_CUR:
|
||||
ctx->Seek(offset,Tesses::Framework::Streams::SeekOrigin::Current);
|
||||
break;
|
||||
case RW_SEEK_END:
|
||||
ctx->Seek(offset,Tesses::Framework::Streams::SeekOrigin::End);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return ctx->GetPosition();
|
||||
}
|
||||
static SDLCALL Sint64 rwops_stream_size(struct SDL_RWops * context)
|
||||
{
|
||||
if(context->hidden.unknown.data1 == nullptr) return -1;
|
||||
auto ctx = static_cast<Tesses::Framework::Streams::Stream*>(context->hidden.unknown.data1);
|
||||
return ctx->GetLength();
|
||||
}
|
||||
static SDLCALL int rwops_stream_close(struct SDL_RWops* context)
|
||||
{
|
||||
if(context->hidden.unknown.data2 == nullptr) return 0;
|
||||
delete static_cast<Tesses::Framework::Streams::Stream*>(context->hidden.unknown.data1);
|
||||
return 0;
|
||||
}
|
||||
SDL_RWops* RwopsFromStream(Tesses::Framework::Streams::Stream* strm, bool owns)
|
||||
{
|
||||
auto rw=SDL_AllocRW();
|
||||
rw->type = SDL_RWOPS_UNKNOWN;
|
||||
rw->hidden.unknown.data1 = static_cast<void*>(strm);
|
||||
rw->hidden.unknown.data2 = (void*)(uintptr_t)(owns?1:0);
|
||||
rw->read = rwops_stream_read;
|
||||
rw->write = rwops_stream_write;
|
||||
rw->seek = rwops_stream_seek;
|
||||
rw->size = rwops_stream_size;
|
||||
rw->close = rwops_stream_close;
|
||||
|
||||
|
||||
return rw;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
173
src/SDL2/View.cpp
Normal file
173
src/SDL2/View.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
#include "TessesFramework/SDL2/GUI.hpp"
|
||||
using namespace Tesses::Framework::Serialization::Json;
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/Views/ButtonView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/CheckView.hpp"
|
||||
#include "TessesFramework/SDL2/Views/LabelView.hpp"
|
||||
namespace Tesses::Framework::SDL2
|
||||
{
|
||||
ContainerView::ContainerView() : View()
|
||||
{
|
||||
this->flags = 0;
|
||||
}
|
||||
ContainerView::ContainerView(std::string text) : View(text)
|
||||
{
|
||||
this->flags = 0;
|
||||
}
|
||||
View::View() : View((std::string){})
|
||||
{
|
||||
|
||||
}
|
||||
View::View(std::string text)
|
||||
{
|
||||
this->text = text;
|
||||
this->flags=VIEWFLAG_TABSTOP;
|
||||
}
|
||||
void View::SetText(std::string text)
|
||||
{
|
||||
this->text=text;
|
||||
}
|
||||
std::string View::GetText()
|
||||
{
|
||||
return this->text;
|
||||
}
|
||||
void View::OnMouseUp(GUIMouseButtonEventArgs& click)
|
||||
{
|
||||
|
||||
}
|
||||
void View::OnMouseDown(GUIMouseButtonEventArgs& click)
|
||||
{
|
||||
|
||||
}
|
||||
void View::OnClick(GUIEventArgs& click)
|
||||
{
|
||||
|
||||
}
|
||||
GUIWindow* View::GetWindow()
|
||||
{
|
||||
if(this->parent ==nullptr) return nullptr;
|
||||
return this->parent->GetWindow();
|
||||
}
|
||||
void View::OnDragDropFile(Tesses::Framework::Filesystem::VFSPath filePath,SDL_Rect myRect, SDL_Point dropLoc)
|
||||
{
|
||||
|
||||
}
|
||||
void View::OnDragDropText(std::string text,SDL_Rect myRect, SDL_Point dropLoc)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void View::OnEnter(GUIEventArgs& evt)
|
||||
{
|
||||
|
||||
}
|
||||
void View::OnLeave(GUIEventArgs& evt)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void View::OnDraw(SDL_Renderer* renderer, SDL_Rect& myRect)
|
||||
{
|
||||
|
||||
}
|
||||
void View::OnSetParent(View* v)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool View::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
||||
{
|
||||
GUISDLEventEventArgs sdle;
|
||||
sdle.event = event;
|
||||
this->SDLEvent.Invoke(this,sdle);
|
||||
if(event.type == SDL_MOUSEBUTTONDOWN)
|
||||
{
|
||||
if(event.button.x >= myVisibleBounds.x && event.button.x < myVisibleBounds.x+myVisibleBounds.w && event.button.y >= myVisibleBounds.y && event.button.y < myVisibleBounds.y+myVisibleBounds.h)
|
||||
{
|
||||
GUIMouseButtonEventArgs cea;
|
||||
cea.button = (int)event.button.button;
|
||||
cea.x = event.button.x - myVisibleBounds.x;
|
||||
cea.y = event.button.y - myVisibleBounds.y;
|
||||
cea.which = event.button.which;
|
||||
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,true);
|
||||
OnMouseDown(cea);
|
||||
this->MouseDown.Invoke(this,cea);
|
||||
}
|
||||
}
|
||||
if(event.type == SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||
{
|
||||
GUIMouseButtonEventArgs cea;
|
||||
cea.button = (int)event.button.button;
|
||||
cea.x = event.button.x - myVisibleBounds.x;
|
||||
cea.y = event.button.y - myVisibleBounds.y;
|
||||
cea.which = event.button.which;
|
||||
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,false);
|
||||
OnMouseUp(cea);
|
||||
this->MouseUp.Invoke(this,cea);
|
||||
GUIEventArgs cea2;
|
||||
OnClick(cea2);
|
||||
this->Click.Invoke(this,cea);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
else if(event.type == SDL_MOUSEMOTION)
|
||||
{
|
||||
bool inside = event.motion.x >= myVisibleBounds.x && event.motion.x < myVisibleBounds.x+myVisibleBounds.w && event.motion.y >= myVisibleBounds.y && event.motion.y < myVisibleBounds.y+myVisibleBounds.h;
|
||||
bool hoverFlag = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||
if(inside && !hoverFlag)
|
||||
{
|
||||
this->SetViewFlag(VIEWFLAG_HOVER_STATE,true);
|
||||
GUIEventArgs e;
|
||||
this->OnEnter(e);
|
||||
this->Enter.Invoke(this,e);
|
||||
}
|
||||
else if(!inside && hoverFlag)
|
||||
{
|
||||
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||
GUIEventArgs e;
|
||||
this->OnLeave(e);
|
||||
this->Leave.Invoke(this,e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::string View::GetId()
|
||||
{
|
||||
return this->id;
|
||||
}
|
||||
void View::SetId(std::string id)
|
||||
{
|
||||
this->id = id;
|
||||
}
|
||||
View* View::FindViewById(std::string id)
|
||||
{
|
||||
if(this->GetId() == id) return this;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
View* ContainerView::FindViewById(std::string id)
|
||||
{
|
||||
if(this->GetId() == id) return this;
|
||||
for(size_t i = 0; i <this->ViewCount(); i++)
|
||||
{
|
||||
auto v = this->GetViewAt(i);
|
||||
auto v2 = v->FindViewById(id);
|
||||
if(v2 != nullptr) return v2;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
View::~View()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
109
src/SDL2/Views/AbsoluteView.cpp
Normal file
109
src/SDL2/Views/AbsoluteView.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
|
||||
|
||||
namespace Tesses::Framework::SDL2::Views
|
||||
{
|
||||
void AbsoluteView::OnDraw(SDL_Renderer* renderer, SDL_Rect& myRect)
|
||||
{
|
||||
Clipper clipper(renderer,myRect);
|
||||
SDL_Rect oldClip;
|
||||
bool isClipped=SDL_RenderIsClipEnabled(renderer);
|
||||
SDL_RenderGetClipRect(renderer,&oldClip);
|
||||
if(!isClipped) oldClip = myRect;
|
||||
|
||||
for(auto& ctrl : this->views)
|
||||
{
|
||||
SDL_Rect childRect = ctrl.second;
|
||||
childRect.x += oldClip.x;
|
||||
childRect.y += oldClip.y;
|
||||
|
||||
|
||||
if(clipper.Clip(childRect))
|
||||
CallOnDraw(ctrl.first.first,renderer,childRect);
|
||||
}
|
||||
|
||||
}
|
||||
bool AbsoluteView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||
{
|
||||
bool handled=false;
|
||||
|
||||
for(auto& item : this->views)
|
||||
{
|
||||
SDL_Rect theirBounds = item.second;
|
||||
theirBounds.x += myBounds.x;
|
||||
theirBounds.y += myBounds.y;
|
||||
|
||||
SDL_Rect theirVisibleBounds = item.second;
|
||||
theirVisibleBounds.x += visibleBounds.x;
|
||||
theirVisibleBounds.y += visibleBounds.y;
|
||||
Clipper::ClipRect(theirVisibleBounds, visibleBounds);
|
||||
|
||||
|
||||
if(CallOnEvent(item.first.first,event,theirBounds, theirVisibleBounds))
|
||||
handled=true;
|
||||
if(handled && event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEMOTION)
|
||||
{
|
||||
GUISDLEventEventArgs sdle;
|
||||
sdle.event = event; this->SDLEvent.Invoke(this,sdle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(handled) {GUISDLEventEventArgs sdle;
|
||||
sdle.event = event; this->SDLEvent.Invoke(this,sdle);return true;}
|
||||
return View::OnEvent(event,myBounds,visibleBounds);
|
||||
}
|
||||
size_t AbsoluteView::ViewCount()
|
||||
{
|
||||
return this->views.size();
|
||||
}
|
||||
View* AbsoluteView::GetViewAt(size_t index)
|
||||
{
|
||||
return this->views.at(index).first.first;
|
||||
}
|
||||
AbsoluteView::AbsoluteView() : ContainerView()
|
||||
{
|
||||
|
||||
}
|
||||
void AbsoluteView::Add(SDL_Rect rect, View* view, bool owns)
|
||||
{
|
||||
for(auto& item : this->views)
|
||||
{
|
||||
if(item.first.first == view) return;
|
||||
}
|
||||
this->AssignChildParentToThis(view);
|
||||
this->views.push_back(std::pair<std::pair<View*,bool>,SDL_Rect>(std::pair<View*,bool>(view,owns),rect));
|
||||
}
|
||||
void AbsoluteView::Set(View* view, SDL_Rect rect)
|
||||
{
|
||||
for(auto& item : this->views)
|
||||
{
|
||||
if(item.first.first == view)
|
||||
{
|
||||
item.second = rect;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void AbsoluteView::Remove(View* view)
|
||||
{
|
||||
for(auto index = this->views.begin(); index != this->views.end(); index++)
|
||||
{
|
||||
if(index->first.first == view)
|
||||
{
|
||||
if(index->first.second) delete index->first.first;
|
||||
this->views.erase(index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AbsoluteView::~AbsoluteView()
|
||||
{
|
||||
for(auto& item : this->views)
|
||||
{
|
||||
if(item.first.second) delete item.first.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
77
src/SDL2/Views/ButtonView.cpp
Normal file
77
src/SDL2/Views/ButtonView.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/Views/ButtonView.hpp"
|
||||
|
||||
namespace Tesses::Framework::SDL2::Views
|
||||
{
|
||||
ButtonView::ButtonView() : View()
|
||||
{
|
||||
|
||||
}
|
||||
ButtonView::ButtonView(std::string text) : View(text)
|
||||
{
|
||||
|
||||
}
|
||||
bool ButtonView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
||||
{
|
||||
if(this->GetViewFlag(VIEWFLAG_ISACTIVE))
|
||||
{
|
||||
if(event.type == SDL_KEYUP)
|
||||
{
|
||||
switch(event.key.keysym.sym)
|
||||
{
|
||||
case SDL_KeyCode::SDLK_SPACE:
|
||||
{
|
||||
GUIEventArgs e;
|
||||
this->OnClick(e);
|
||||
this->Click.Invoke(this,e);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(event.type == SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
if(event.button.x >= myVisibleBounds.x && event.button.x < myVisibleBounds.x+myVisibleBounds.w && event.button.y >= myVisibleBounds.y && event.button.y < myVisibleBounds.y+myVisibleBounds.h)
|
||||
{
|
||||
this->GetWindow()->MakeActive(this);
|
||||
}
|
||||
}
|
||||
return View::OnEvent(event,myBounds,myVisibleBounds);
|
||||
}
|
||||
void ButtonView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||
{
|
||||
auto win = this->GetWindow();
|
||||
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||
SDL_RenderFillRect(renderer,&r);
|
||||
int textW;
|
||||
int textH;
|
||||
win->normal_font->CalculateSize(this->text,textW,textH);
|
||||
|
||||
int x=(r.w/2)-(textW/2);
|
||||
int y=(r.h/2)-(textH/2);
|
||||
x+=r.x;
|
||||
y+=r.y;
|
||||
|
||||
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||
|
||||
SDL_Color& color = win->palette.GetBorderColor(isHovering,isActive,isMouseDown);
|
||||
|
||||
win->normal_font->Render(renderer,x,y,this->text,color);
|
||||
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
|
||||
|
||||
SDL_Rect r2={.x=r.x,.y=r.y,.w=r.w,.h=r.h};
|
||||
for(size_t i=0;i < 4; i++)
|
||||
{
|
||||
SDL_RenderDrawRect(renderer,&r2);
|
||||
r2.x++;
|
||||
r2.y++;
|
||||
r2.w-=2;
|
||||
r2.h-=2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
122
src/SDL2/Views/CheckView.cpp
Normal file
122
src/SDL2/Views/CheckView.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/Views/CheckView.hpp"
|
||||
|
||||
namespace Tesses::Framework::SDL2::Views
|
||||
{
|
||||
void CheckView::OnCheckChanged(GUIEventArgs& event)
|
||||
{
|
||||
|
||||
}
|
||||
void CheckView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||
{
|
||||
auto win = this->GetWindow();
|
||||
|
||||
const int checkSz=32;
|
||||
|
||||
SDL_Rect checkBoxRect={.x=r.x,.y=r.y+((r.h/2)-(checkSz/2)),.w=checkSz,.h=checkSz};
|
||||
|
||||
int textW;
|
||||
int textH;
|
||||
win->normal_font->CalculateSize(this->text,textW,textH);
|
||||
|
||||
//we only need the y
|
||||
|
||||
int x = r.x+checkSz+8;
|
||||
int y = r.y+((r.h/2)-(textH/2));
|
||||
|
||||
win->normal_font->Render(renderer,x,y,text,win->palette.accent);
|
||||
|
||||
|
||||
|
||||
if(this->GetViewFlag(VIEWFLAG_CHECKED))
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||
|
||||
//x=0,y=0.5, x=0.5, y=1
|
||||
|
||||
int x1=checkBoxRect.x+4;
|
||||
int y1=checkBoxRect.y+4+((checkSz-8)/2);
|
||||
int x2=checkBoxRect.x+4+((checkSz-8)/2);
|
||||
int y2=checkBoxRect.y+4+(checkSz-8);
|
||||
|
||||
int x3=checkBoxRect.x+4+(checkSz-8);
|
||||
int y3=checkBoxRect.y+4;
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
SDL_RenderDrawLine(renderer,x1,y1-i,x2,y2-i);
|
||||
SDL_RenderDrawLine(renderer,x2-i,y2,x3-i,y3);
|
||||
}
|
||||
}
|
||||
|
||||
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||
|
||||
SDL_Color& color = win->palette.GetBorderColor(isHovering,isActive,isMouseDown);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
{
|
||||
SDL_RenderDrawRect(renderer,&checkBoxRect);
|
||||
checkBoxRect.x++;
|
||||
checkBoxRect.y++;
|
||||
checkBoxRect.w-=2;
|
||||
checkBoxRect.h-=2;
|
||||
}
|
||||
}
|
||||
bool CheckView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||
{
|
||||
if(this->GetViewFlag(VIEWFLAG_ISACTIVE))
|
||||
{
|
||||
if(event.type == SDL_KEYUP)
|
||||
{
|
||||
switch(event.key.keysym.sym)
|
||||
{
|
||||
case SDL_KeyCode::SDLK_SPACE:
|
||||
{
|
||||
GUIEventArgs e;
|
||||
|
||||
this->SetViewFlag(VIEWFLAG_CHECKED,!this->GetViewFlag(VIEWFLAG_CHECKED));
|
||||
this->OnClick(e);
|
||||
this->Click.Invoke(this,e);
|
||||
this->OnCheckChanged(e);
|
||||
this->CheckChanged.Invoke(this,e);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(event.type == SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
if(event.button.x >= visibleBounds.x && event.button.x < visibleBounds.x+visibleBounds.w && event.button.y >= visibleBounds.y && event.button.y < visibleBounds.y+visibleBounds.h)
|
||||
{
|
||||
this->GetWindow()->MakeActive(this);
|
||||
this->SetViewFlag(VIEWFLAG_CHECKED,!this->GetViewFlag(VIEWFLAG_CHECKED));
|
||||
GUIEventArgs e;
|
||||
this->OnCheckChanged(e);
|
||||
this->CheckChanged.Invoke(this,e);
|
||||
}
|
||||
}
|
||||
return View::OnEvent(event,myBounds,visibleBounds);
|
||||
}
|
||||
|
||||
CheckView::CheckView(bool checked, std::string label) : View(label)
|
||||
{
|
||||
this->SetViewFlag(VIEWFLAG_CHECKED,checked);
|
||||
}
|
||||
CheckView::CheckView() : View()
|
||||
{
|
||||
this->SetViewFlag(VIEWFLAG_CHECKED,false);
|
||||
}
|
||||
|
||||
bool CheckView::GetChecked()
|
||||
{
|
||||
return this->GetViewFlag(VIEWFLAG_CHECKED);
|
||||
}
|
||||
void CheckView::SetChecked(bool value)
|
||||
{
|
||||
this->SetViewFlag(VIEWFLAG_CHECKED,true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
20
src/SDL2/Views/LabelView.cpp
Normal file
20
src/SDL2/Views/LabelView.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include "TessesFramework/SDL2/Views/LabelView.hpp"
|
||||
namespace Tesses::Framework::SDL2::Views
|
||||
{
|
||||
void LabelView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||
{
|
||||
auto win =this->GetWindow();
|
||||
win->normal_font->Render(renderer,r.x+4,r.y+4,text,win->palette.accent);
|
||||
}
|
||||
|
||||
LabelView::LabelView() : View()
|
||||
{
|
||||
this->flags &= ~VIEWFLAG_TABSTOP;
|
||||
}
|
||||
LabelView::LabelView(std::string text) : View(text)
|
||||
{
|
||||
this->flags &= ~VIEWFLAG_TABSTOP;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
39
src/SDL2/Views/ProgressView.cpp
Normal file
39
src/SDL2/Views/ProgressView.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
|
||||
#include "TessesFramework/SDL2/Views/ProgressView.hpp"
|
||||
|
||||
namespace Tesses::Framework::SDL2::Views
|
||||
{
|
||||
ProgressView::ProgressView() : ProgressView(0.0)
|
||||
{
|
||||
|
||||
}
|
||||
ProgressView::ProgressView(double v) : View()
|
||||
{
|
||||
this->value = v;
|
||||
this->SetViewFlag(VIEWFLAG_TABSTOP,false);
|
||||
}
|
||||
void ProgressView::OnDraw(SDL_Renderer* renderer, SDL_Rect& rect)
|
||||
{
|
||||
auto win = this->GetWindow();
|
||||
|
||||
|
||||
SDL_SetRenderDrawColor(renderer,win->palette.border_color.r,win->palette.border_color.g,win->palette.border_color.b,win->palette.border_color.a);
|
||||
|
||||
SDL_Rect r2={.x=rect.x,.y=rect.y,.w=rect.w,.h=rect.h};
|
||||
for(size_t i=0;i < 4; i++)
|
||||
{
|
||||
SDL_RenderDrawRect(renderer,&r2);
|
||||
r2.x++;
|
||||
r2.y++;
|
||||
r2.w-=2;
|
||||
r2.h-=2;
|
||||
}
|
||||
|
||||
auto res = (int)((rect.w-8)*(this->value/100.0));
|
||||
r2={.x=rect.x+4,.y=rect.y+4,.w=res,.h=rect.h-8};
|
||||
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||
SDL_RenderFillRect(renderer,&r2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
140
src/SDL2/Views/TextListView.cpp
Normal file
140
src/SDL2/Views/TextListView.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
|
||||
#include "TessesFramework/SDL2/Views/TextListView.hpp"
|
||||
|
||||
namespace Tesses::Framework::SDL2::Views
|
||||
{
|
||||
TextListView::TextListView() : View()
|
||||
{
|
||||
this->firstIndex=0;
|
||||
this->selected=-1;
|
||||
}
|
||||
bool TextListView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||
{
|
||||
auto win = this->GetWindow();
|
||||
auto item_height = win->normal_font->MaxHeight()+8;
|
||||
auto no_items = (myBounds.h-8) / item_height;
|
||||
|
||||
if(this->items.size() > no_items)
|
||||
{
|
||||
|
||||
if(this->items.size() - this->firstIndex < no_items)
|
||||
{
|
||||
this->firstIndex = this->items.size() - no_items;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
this->firstIndex=0;
|
||||
|
||||
no_items = (int)this->items.size();
|
||||
}
|
||||
if(event.type == SDL_KEYDOWN)
|
||||
{
|
||||
if(this->GetViewFlag(VIEWFLAG_ISACTIVE))
|
||||
{
|
||||
switch(event.key.keysym.sym)
|
||||
{
|
||||
case SDLK_HOME:
|
||||
this->selected=0;
|
||||
this->firstIndex=0;
|
||||
break;
|
||||
case SDLK_END:
|
||||
this->selected = (int)(this->items.size()-1);
|
||||
this->firstIndex = (this->selected/no_items) * no_items;
|
||||
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
this->selected++;
|
||||
if(this->selected < -1 || this->selected >= this->items.size())
|
||||
{
|
||||
this->selected=0;
|
||||
}
|
||||
this->firstIndex = (this->selected/no_items) * no_items;
|
||||
break;
|
||||
case SDLK_UP:
|
||||
this->selected--;
|
||||
if(this->selected < 0 || this->selected >= this->items.size())
|
||||
{
|
||||
this->selected = (int)(this->items.size()-1);
|
||||
}
|
||||
|
||||
this->firstIndex = (this->selected/no_items) * no_items;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(event.type == SDL_MOUSEBUTTONUP && event.button.x >= (visibleBounds.x+4) && event.button.x < (visibleBounds.x+visibleBounds.w)-8 && event.button.y >= (visibleBounds.y+4) && event.button.y < (visibleBounds.y+visibleBounds.h)-8)
|
||||
{
|
||||
win->MakeActive(this);
|
||||
auto myRealY=event.button.y - (myBounds.y+4);
|
||||
auto yThing = myRealY / item_height;
|
||||
|
||||
if(yThing < no_items)
|
||||
{
|
||||
auto high= yThing+this->firstIndex;
|
||||
this->selected = (int)high;
|
||||
}
|
||||
|
||||
}
|
||||
return View::OnEvent(event,myBounds,visibleBounds);
|
||||
}
|
||||
|
||||
void TextListView::OnDraw(SDL_Renderer* renderer,SDL_Rect& rect)
|
||||
{
|
||||
auto win = this->GetWindow();
|
||||
auto item_height = win->normal_font->MaxHeight()+8;
|
||||
auto no_items = (rect.h-8) / item_height;
|
||||
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||
|
||||
SDL_Color& color = win->palette.GetBorderColor(isHovering,isActive,isMouseDown);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if(this->items.size() > no_items)
|
||||
{
|
||||
|
||||
if(this->items.size() - this->firstIndex < no_items)
|
||||
{
|
||||
this->firstIndex = this->items.size() - no_items;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->firstIndex=0;
|
||||
no_items = (int)this->items.size();
|
||||
}
|
||||
|
||||
SDL_Rect r2={.x=rect.x,.y=rect.y,.w=rect.w,.h=rect.h};
|
||||
for(size_t i=0;i < 4; i++)
|
||||
{
|
||||
SDL_RenderDrawRect(renderer,&r2);
|
||||
r2.x++;
|
||||
r2.y++;
|
||||
r2.w-=2;
|
||||
r2.h-=2;
|
||||
}
|
||||
|
||||
for(int i = 0; i < no_items; i++)
|
||||
{
|
||||
int realI = i+(int)firstIndex;
|
||||
if(realI == this->selected)
|
||||
{
|
||||
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||
SDL_Rect r2={.x=rect.x+4,.y=rect.y+4+(item_height*i),.w=rect.w-8,.h=item_height};
|
||||
SDL_RenderFillRect(renderer,&r2);
|
||||
win->normal_font->Render(renderer,rect.x+12,(rect.y+12)+(item_height*i),this->items[realI],color);
|
||||
}
|
||||
else {
|
||||
win->normal_font->Render(renderer,rect.x+12,(rect.y+12)+(item_height*i),this->items[realI],win->palette.accent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -43,7 +43,7 @@ extern "C" {
|
||||
#if defined(GEKKO)
|
||||
|
||||
extern "C" uint32_t if_config( char *local_ip, char *netmask, char *gateway,bool use_dhcp, int max_retries);
|
||||
#elif !defined(_WIN32) && !defined(__ANDROID__) && !defined(__SWITCH__)
|
||||
#elif !defined(_WIN32) && !defined(__ANDROID__) && !defined(__SWITCH__) && !defined(__PS2__)
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace Tesses::Framework::Streams {
|
||||
free(addresses);
|
||||
|
||||
|
||||
#elif defined(__ANDROID__) || defined(__SWITCH__)
|
||||
#elif defined(__ANDROID__) || defined(__SWITCH__) || defined(__PS2__)
|
||||
|
||||
#else
|
||||
struct ifaddrs *ifAddrStruct = NULL;
|
||||
@@ -181,7 +181,12 @@ namespace Tesses::Framework::Streams {
|
||||
{
|
||||
memset(addr,0,sizeof(struct sockaddr_storage));
|
||||
uint8_t ip[16];
|
||||
|
||||
#if defined(__PS2__)
|
||||
if(inet_aton(str.c_str(),ip) == 1)
|
||||
#else
|
||||
if(inet_pton(AF_INET,str.c_str(),ip)==1)
|
||||
#endif
|
||||
{
|
||||
struct sockaddr_in* inAddr = (struct sockaddr_in*)addr;
|
||||
inAddr->sin_family = AF_INET;
|
||||
@@ -521,25 +526,46 @@ namespace Tesses::Framework::Streams {
|
||||
{
|
||||
return this->success;
|
||||
}
|
||||
NetworkStream::NetworkStream(bool ipV6,bool datagram)
|
||||
NetworkStream::NetworkStream(SocketType type)
|
||||
{
|
||||
this->endOfStream=false;
|
||||
this->owns = true;
|
||||
this->success=false;
|
||||
if(ipV6)
|
||||
switch(type)
|
||||
{
|
||||
#if defined(AF_INET6)
|
||||
this->sock = NETWORK_SOCKET(AF_INET6, datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
if(this->sock >= 0) this->success=true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(AF_INET)
|
||||
this->sock = NETWORK_SOCKET(AF_INET, datagram ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
if(this->sock >= 0) this->success=true;
|
||||
case SocketType::ST_IPv4_TCP:
|
||||
#if defined(AF_INET)
|
||||
this->sock = NETWORK_SOCKET(AF_INET,SOCK_STREAM, 0);
|
||||
|
||||
#endif
|
||||
break;
|
||||
case SocketType::ST_IPv4_UDP:
|
||||
#if defined(AF_INET)
|
||||
this->sock = NETWORK_SOCKET(AF_INET,SOCK_DGRAM, 0);
|
||||
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SocketType::ST_IPv6_TCP:
|
||||
#if defined(AF_INET6)
|
||||
this->sock = NETWORK_SOCKET(AF_INET6,SOCK_STREAM, 0);
|
||||
|
||||
#endif
|
||||
break;
|
||||
case SocketType::ST_IPv6_UDP:
|
||||
#if defined(AF_INET6)
|
||||
this->sock = NETWORK_SOCKET(AF_INET6,SOCK_DGRAM, 0);
|
||||
|
||||
#endif
|
||||
break;
|
||||
case SocketType::ST_UNIX:
|
||||
#if defined(AF_UNIX)
|
||||
this->sock = NETWORK_SOCKET(AF_UNIX,SOCK_DGRAM, 0);
|
||||
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if(this->sock >= 0) this->success=true;
|
||||
}
|
||||
NetworkStream::NetworkStream(std::string ipOrFqdn, uint16_t port, bool datagram, bool broadcast, bool supportIPv6)
|
||||
{
|
||||
@@ -672,7 +698,7 @@ namespace Tesses::Framework::Streams {
|
||||
ip = StringifyIP((struct sockaddr*)&storage);
|
||||
port = getPort((struct sockaddr*)&storage);
|
||||
|
||||
return new NetworkStream(s,true);
|
||||
return new NetworkStream((int32_t)s,(bool)true);
|
||||
}
|
||||
size_t NetworkStream::Read(uint8_t* buff, size_t sz)
|
||||
{
|
||||
@@ -797,7 +823,7 @@ bool NetworkStream::CanWrite() {
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkStream::NetworkStream(bool ipV6,bool datagram)
|
||||
NetworkStream::NetworkStream(SocketType type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
132
src/Streams/PtyStream.cpp
Normal file
132
src/Streams/PtyStream.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "TessesFramework/Streams/PtyStream.hpp"
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32)
|
||||
#include <pty.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
#endif
|
||||
namespace Tesses::Framework::Streams {
|
||||
PtyStream::PtyStream(WindowSize windowSize,std::string filename, std::vector<std::string> args, std::vector<std::string> env)
|
||||
{
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32)
|
||||
this->wS = windowSize;
|
||||
this->eos=false;
|
||||
winsize sz;
|
||||
sz.ws_col =(unsigned short)windowSize.Columns;
|
||||
sz.ws_row = (unsigned short)windowSize.Rows;
|
||||
sz.ws_xpixel = (unsigned short)windowSize.Width;
|
||||
sz.ws_ypixel = (unsigned short)windowSize.Height;
|
||||
termios ios;
|
||||
cfmakeraw(&ios);
|
||||
|
||||
pid= forkpty(&this->socket,NULL,&ios,&sz);
|
||||
if(pid == -1)
|
||||
{
|
||||
this->eos=true;
|
||||
}
|
||||
if(pid == 0)
|
||||
{
|
||||
char** argv = new char*[args.size()+1];
|
||||
argv[args.size()]=NULL;
|
||||
char** envp = new char*[env.size()+1];
|
||||
envp[env.size()]=NULL;
|
||||
|
||||
for(size_t i = 0; i < args.size();i++)
|
||||
{
|
||||
argv[i] = (char*)args[i].c_str();
|
||||
}
|
||||
for(size_t i = 0; i < env.size();i++)
|
||||
{
|
||||
envp[i] = (char*)env[i].c_str();
|
||||
}
|
||||
|
||||
if(execve(filename.c_str(),argv,envp) == -1)
|
||||
{
|
||||
perror("execve returned -1");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
int flags = fcntl(this->socket, F_GETFL, 0);
|
||||
if(flags == -1) {
|
||||
perror("fcntl F_GETFL");
|
||||
this->eos=true;
|
||||
return;
|
||||
}
|
||||
flags |= O_NONBLOCK;
|
||||
|
||||
flags=fcntl(this->socket,F_SETFL,flags);
|
||||
if(flags == -1) {
|
||||
perror("fcntl F_SETFL");
|
||||
|
||||
this->eos=true;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
bool PtyStream::EndOfStream()
|
||||
{
|
||||
return this->eos;
|
||||
}
|
||||
bool PtyStream::CanRead()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool PtyStream::CanWrite()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
size_t PtyStream::Read(uint8_t* buff, size_t sz)
|
||||
{
|
||||
if(this->eos) return 0;
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32)
|
||||
auto res = read(this->socket, buff,sz);
|
||||
|
||||
if(res == -1)
|
||||
{
|
||||
if(errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
this->eos=true;
|
||||
return 0;
|
||||
}
|
||||
return (size_t)res;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
size_t PtyStream::Write(const uint8_t* buff, size_t sz)
|
||||
{
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32)
|
||||
auto res = write(this->socket, buff,sz);
|
||||
return res;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
WindowSize PtyStream::GetWindowSize()
|
||||
{
|
||||
return this->wS;
|
||||
}
|
||||
void PtyStream::Resize(WindowSize windowSize)
|
||||
{
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32)
|
||||
this->wS = windowSize;
|
||||
winsize sz;
|
||||
sz.ws_col =(unsigned short)windowSize.Columns;
|
||||
sz.ws_row = (unsigned short)windowSize.Rows;
|
||||
sz.ws_xpixel = (unsigned short)windowSize.Width;
|
||||
sz.ws_ypixel = (unsigned short)windowSize.Height;
|
||||
|
||||
ioctl(this->socket,TIOCSWINSZ,&sz);
|
||||
#endif
|
||||
}
|
||||
PtyStream::~PtyStream()
|
||||
{
|
||||
this->eos=true;
|
||||
#if !defined(GEKKO) && !defined(__PS2__) && !defined(_WIN32)
|
||||
close(this->socket);
|
||||
|
||||
kill((pid_t)this->pid,SIGHUP);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "TessesFramework/Streams/NetworkStream.hpp"
|
||||
#include <atomic>
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#undef min
|
||||
@@ -35,6 +36,9 @@ static GXRModeObj *rmode = NULL;
|
||||
#endif
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include "TessesFramework/SDL2/GUI.hpp"
|
||||
#endif
|
||||
|
||||
namespace Tesses::Framework
|
||||
@@ -87,6 +91,7 @@ namespace Tesses::Framework
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
||||
Tesses::Framework::Threading::LookForFinishedThreads();
|
||||
#endif
|
||||
|
||||
|
||||
if(!isRunningSig) isRunning=false;
|
||||
#if defined(GEKKO)
|
||||
@@ -115,6 +120,9 @@ namespace Tesses::Framework
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
Tesses::Framework::SDL2::gui.Update();
|
||||
#endif
|
||||
}
|
||||
void TF_SetIsRunning(bool _isRunning)
|
||||
{
|
||||
@@ -135,6 +143,14 @@ namespace Tesses::Framework
|
||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||
//SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS,"1");
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
TTF_Init();
|
||||
int r = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF | IMG_INIT_WEBP | IMG_INIT_JXL |IMG_INIT_AVIF;
|
||||
if(IMG_Init(
|
||||
r
|
||||
) != r)
|
||||
{
|
||||
std::cout << "IMG_Init: " << IMG_GetError() << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
tzset();
|
||||
|
||||
36
src/TextStreams/StdIOReader.cpp
Normal file
36
src/TextStreams/StdIOReader.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "TessesFramework/TextStreams/StdIOReader.hpp"
|
||||
|
||||
|
||||
namespace Tesses::Framework::TextStreams
|
||||
{
|
||||
ConsoleReader::ConsoleReader()
|
||||
{
|
||||
|
||||
}
|
||||
bool ConsoleReader::ReadBlock(std::string& str,size_t len)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
uint8_t* buff = new uint8_t[len];
|
||||
#else
|
||||
uint8_t buff[len];
|
||||
#endif
|
||||
size_t read=0;
|
||||
size_t readTotal=0;
|
||||
uint8_t* buffOff=buff;
|
||||
do {
|
||||
read=fread(buffOff,1,len,stdin);
|
||||
if(read != 0) {readTotal+= read;len-=read; buffOff+=read;}
|
||||
} while(read != 0);
|
||||
if(readTotal == 0) return false;
|
||||
str.append((const char*)buff, readTotal);
|
||||
#if defined(_WIN32)
|
||||
delete buff;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
ConsoleReader StdIn()
|
||||
{
|
||||
return ConsoleReader();
|
||||
}
|
||||
}
|
||||
42
src/TextStreams/StdIOWriter.cpp
Normal file
42
src/TextStreams/StdIOWriter.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include "TessesFramework/TextStreams/StdIOWriter.hpp"
|
||||
#if defined(__PS2__)
|
||||
#include <debug.h>
|
||||
#else
|
||||
#include <cstdio>
|
||||
#endif
|
||||
namespace Tesses::Framework::TextStreams
|
||||
{
|
||||
ConsoleWriter::ConsoleWriter(bool isError) : TextWriter()
|
||||
{
|
||||
this->isError=isError;
|
||||
}
|
||||
|
||||
void ConsoleWriter::WriteData(const char* text, size_t len)
|
||||
{
|
||||
#if defined(__PS2__)
|
||||
char lenThing[10];//%.2048s
|
||||
while(len > 0) {
|
||||
int b = std::min((int)2047,(int)len);
|
||||
snprintf(lenThing,18,"%%.%is",b);
|
||||
|
||||
scr_printf(lenThing,text);
|
||||
|
||||
len -= b;
|
||||
text += b;
|
||||
}
|
||||
#else
|
||||
if(isError)
|
||||
fwrite(text,1,len,stderr);
|
||||
else
|
||||
fwrite(text,1,len,stdout);
|
||||
#endif
|
||||
}
|
||||
ConsoleWriter StdOut()
|
||||
{
|
||||
return ConsoleWriter(false);
|
||||
}
|
||||
ConsoleWriter StdErr()
|
||||
{
|
||||
return ConsoleWriter(true);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,15 @@ namespace Tesses::Framework::TextStreams {
|
||||
StreamReader::StreamReader(std::filesystem::path path) : StreamReader(new FileStream(path,"rb"),true)
|
||||
{
|
||||
|
||||
}
|
||||
bool StreamReader::Rewind()
|
||||
{
|
||||
if(this->strm->CanSeek())
|
||||
{
|
||||
this->strm->Seek((int64_t)0,Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
StreamReader::StreamReader(Stream* strm, bool owns) : TextReader()
|
||||
{
|
||||
|
||||
38
src/TextStreams/StringReader.cpp
Normal file
38
src/TextStreams/StringReader.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "TessesFramework/TextStreams/StringReader.hpp"
|
||||
|
||||
namespace Tesses::Framework::TextStreams {
|
||||
StringReader::StringReader()
|
||||
{
|
||||
this->offset=0;
|
||||
this->str="";
|
||||
}
|
||||
StringReader::StringReader(std::string str)
|
||||
{
|
||||
this->offset=0;
|
||||
this->str=str;
|
||||
}
|
||||
size_t& StringReader::GetOffset()
|
||||
{
|
||||
return this->offset;
|
||||
}
|
||||
std::string& StringReader::GetString()
|
||||
{
|
||||
return this->str;
|
||||
}
|
||||
bool StringReader::Rewind()
|
||||
{
|
||||
this->offset=0;
|
||||
return true;
|
||||
}
|
||||
bool StringReader::ReadBlock(std::string& str,size_t sz)
|
||||
{
|
||||
if(this->offset < this->str.size())
|
||||
{
|
||||
size_t len = std::min(sz,this->str.size()-this->offset);
|
||||
str.insert(str.size(),this->str.data()+this->offset,len);
|
||||
offset+=len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
21
src/TextStreams/StringWriter.cpp
Normal file
21
src/TextStreams/StringWriter.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "TessesFramework/TextStreams/StringWriter.hpp"
|
||||
|
||||
namespace Tesses::Framework::TextStreams
|
||||
{
|
||||
std::string& StringWriter::GetString()
|
||||
{
|
||||
return this->text;
|
||||
}
|
||||
StringWriter::StringWriter() : TextWriter()
|
||||
{
|
||||
|
||||
}
|
||||
StringWriter::StringWriter(std::string str) : TextWriter()
|
||||
{
|
||||
this->text = str;
|
||||
}
|
||||
void StringWriter::WriteData(const char* text, size_t len)
|
||||
{
|
||||
this->text.append(text,len);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace Tesses::Framework::TextStreams
|
||||
{
|
||||
bool TextReader::Rewind()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int32_t TextReader::ReadChar()
|
||||
{
|
||||
std::string txt;
|
||||
|
||||
@@ -1,7 +1,91 @@
|
||||
#include "TessesFramework/TextStreams/TextWriter.hpp"
|
||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||
|
||||
namespace Tesses::Framework::TextStreams
|
||||
{
|
||||
void TextWriter::Write(int64_t n)
|
||||
{
|
||||
std::string text = std::to_string(n);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::Write(uint64_t n)
|
||||
{
|
||||
std::string text = std::to_string(n);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
|
||||
void TextWriter::Write(const void* ptr)
|
||||
{
|
||||
std::string text = "0x";
|
||||
uintptr_t ptr2 = (uintptr_t)ptr;
|
||||
|
||||
for(size_t i = 1; i <= sizeof(ptr); i++)
|
||||
{
|
||||
uint8_t v = (uint8_t)(ptr2 >> (int)((sizeof(ptr) - i) * 8));
|
||||
text.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex(v >> 4));
|
||||
text.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex(v));
|
||||
}
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::Write(const char* ptr)
|
||||
{
|
||||
WriteData(ptr,strlen(ptr));
|
||||
}
|
||||
void TextWriter::Write(char c)
|
||||
{
|
||||
WriteData(&c,1);
|
||||
}
|
||||
void TextWriter::Write(double d)
|
||||
{
|
||||
std::string text = std::to_string(d);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
|
||||
|
||||
void TextWriter::WriteLine(int64_t n)
|
||||
{
|
||||
std::string text = std::to_string(n);
|
||||
text.append(newline);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::WriteLine(uint64_t n)
|
||||
{
|
||||
std::string text = std::to_string(n);
|
||||
text.append(newline);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::WriteLine(const void* ptr)
|
||||
{
|
||||
std::string text = "0x";
|
||||
uintptr_t ptr2 = (uintptr_t)ptr;
|
||||
|
||||
for(size_t i = 1; i <= sizeof(ptr); i++)
|
||||
{
|
||||
uint8_t v = (uint8_t)(ptr2 >> (int)((sizeof(ptr) - i) * 8));
|
||||
text.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex(v >> 4));
|
||||
text.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex(v));
|
||||
}
|
||||
text.append(newline);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::WriteLine(const char* ptr)
|
||||
{
|
||||
std::string text = ptr;
|
||||
text.append(newline);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::WriteLine(char c)
|
||||
{
|
||||
std::string text = {c};
|
||||
text.append(newline);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
void TextWriter::WriteLine(double d)
|
||||
{
|
||||
std::string text = std::to_string(d);
|
||||
text.append(newline);
|
||||
WriteData(text.c_str(),text.size());
|
||||
}
|
||||
TextWriter::TextWriter()
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
|
||||
Reference in New Issue
Block a user