Compare commits
10 Commits
81f0d3be2e
...
f1dca82107
| Author | SHA1 | Date | |
|---|---|---|---|
| f1dca82107 | |||
| 7199939260 | |||
| c92f003cf2 | |||
| 4040dfe98f | |||
| 55408a3f1b | |||
| 3877c1391d | |||
| e4f75b69a6 | |||
| 4547fda283 | |||
| dbfb7c1133 | |||
| 0c1bf41f17 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
build
|
build
|
||||||
builds
|
builds
|
||||||
.vscode
|
.vscode
|
||||||
|
out
|
||||||
|
/.vs
|
||||||
|
|||||||
@ -19,6 +19,7 @@ src/Mail/Smtp.cpp
|
|||||||
src/Serialization/Json.cpp
|
src/Serialization/Json.cpp
|
||||||
src/Serialization/SQLite.cpp
|
src/Serialization/SQLite.cpp
|
||||||
src/Platform/Environment.cpp
|
src/Platform/Environment.cpp
|
||||||
|
src/Platform/Process.cpp
|
||||||
src/Streams/FileStream.cpp
|
src/Streams/FileStream.cpp
|
||||||
src/Streams/MemoryStream.cpp
|
src/Streams/MemoryStream.cpp
|
||||||
src/Streams/NetworkStream.cpp
|
src/Streams/NetworkStream.cpp
|
||||||
@ -27,6 +28,7 @@ src/Streams/BufferedStream.cpp
|
|||||||
src/Streams/ByteReader.cpp
|
src/Streams/ByteReader.cpp
|
||||||
src/Streams/ByteWriter.cpp
|
src/Streams/ByteWriter.cpp
|
||||||
src/Streams/PtyStream.cpp
|
src/Streams/PtyStream.cpp
|
||||||
|
src/Text/StringConverter.cpp
|
||||||
src/TextStreams/StreamReader.cpp
|
src/TextStreams/StreamReader.cpp
|
||||||
src/TextStreams/StreamWriter.cpp
|
src/TextStreams/StreamWriter.cpp
|
||||||
src/TextStreams/TextReader.cpp
|
src/TextStreams/TextReader.cpp
|
||||||
@ -53,16 +55,22 @@ src/SDL2/FontCache.cpp
|
|||||||
src/SDL2/Stream.cpp
|
src/SDL2/Stream.cpp
|
||||||
src/SDL2/GUI.cpp
|
src/SDL2/GUI.cpp
|
||||||
src/SDL2/GUIWindow.cpp
|
src/SDL2/GUIWindow.cpp
|
||||||
|
src/SDL2/GUIPopup.cpp
|
||||||
src/SDL2/View.cpp
|
src/SDL2/View.cpp
|
||||||
src/SDL2/Views/ButtonView.cpp
|
src/SDL2/Views/ButtonView.cpp
|
||||||
src/SDL2/Views/AbsoluteView.cpp
|
src/SDL2/Views/AbsoluteView.cpp
|
||||||
src/SDL2/Views/LabelView.cpp
|
src/SDL2/Views/LabelView.cpp
|
||||||
src/SDL2/Views/TextListView.cpp
|
src/SDL2/Views/TextListView.cpp
|
||||||
|
src/SDL2/Views/ScrollableTextListView.cpp
|
||||||
src/SDL2/Views/ProgressView.cpp
|
src/SDL2/Views/ProgressView.cpp
|
||||||
src/SDL2/Views/CheckView.cpp
|
src/SDL2/Views/CheckView.cpp
|
||||||
src/SDL2/Views/EditTextView.cpp
|
src/SDL2/Views/EditTextView.cpp
|
||||||
src/SDL2/Views/PictureView.cpp
|
src/SDL2/Views/PictureView.cpp
|
||||||
|
src/SDL2/Views/VScrollView.cpp
|
||||||
|
src/SDL2/Views/HScrollView.cpp
|
||||||
|
src/SDL2/Views/VStackView.cpp
|
||||||
|
src/SDL2/Views/HStackView.cpp
|
||||||
|
src/SDL2/Views/DropDownView.cpp
|
||||||
)
|
)
|
||||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||||
|
|
||||||
@ -93,12 +101,17 @@ option(TESSESFRAMEWORK_ENABLE_SETDATE "Enable setting date to file" ON)
|
|||||||
option(TESSESFRAMEWORK_LOGTOFILE "TessesFramework Log to file" OFF)
|
option(TESSESFRAMEWORK_LOGTOFILE "TessesFramework Log to file" OFF)
|
||||||
option(TESSESFRAMEWORK_ENABLE_SDL2 "Enable SDL2" OFF)
|
option(TESSESFRAMEWORK_ENABLE_SDL2 "Enable SDL2" OFF)
|
||||||
option(TESSESFRAMEWORK_FETCHCONTENT "TessesFramework fetchcontent" OFF)
|
option(TESSESFRAMEWORK_FETCHCONTENT "TessesFramework fetchcontent" OFF)
|
||||||
|
option(TESSESFRAMEWORK_VENDERCERTCHAIN "Use the ca-certificates.crt in project rather than system" ON)
|
||||||
if(TESSESFRAMEWORK_FETCHCONTENT)
|
if(TESSESFRAMEWORK_FETCHCONTENT)
|
||||||
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
else()
|
else()
|
||||||
|
if(TESSESFRAMEWORK_VENDERCERTCHAIN)
|
||||||
|
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||||
|
else()
|
||||||
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain")
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include)
|
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||||
|
|
||||||
@ -148,8 +161,8 @@ set(USE_SHARED_MBEDTLS_LIBRARY ON)
|
|||||||
endif()
|
endif()
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
mbedtls
|
mbedtls
|
||||||
GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git
|
URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.3.1.tar.bz2
|
||||||
GIT_PROGRESS TRUE
|
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(mbedtls)
|
FetchContent_MakeAvailable(mbedtls)
|
||||||
else()
|
else()
|
||||||
@ -281,14 +294,15 @@ endif()
|
|||||||
add_library(tessesframework_shared SHARED ${TESSESFRAMEWORK_SOURCE})
|
add_library(tessesframework_shared SHARED ${TESSESFRAMEWORK_SOURCE})
|
||||||
TESSESFRAMEWORK_LINKDEPS(tessesframework_shared)
|
TESSESFRAMEWORK_LINKDEPS(tessesframework_shared)
|
||||||
|
|
||||||
if(TESSESFRAMEWORK_FETCHCONTENT AND TESSESFRAMEWORK_ENABLE_MBED)
|
if(TESSESFRAMEWORK_ENABLE_MBED)
|
||||||
|
if(TESSESFRAMEWORK_FETCHCONTENT)
|
||||||
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m)
|
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m)
|
||||||
|
|
||||||
else()
|
else()
|
||||||
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto)
|
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
list(APPEND TessesFrameworkLibs tessesframework_shared)
|
list(APPEND TessesFrameworkLibs tessesframework_shared)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -387,6 +401,9 @@ install(TARGETS tjsonunpretty DESTINATION bin)
|
|||||||
add_executable(ttime apps/ttime.cpp)
|
add_executable(ttime apps/ttime.cpp)
|
||||||
target_link_libraries(ttime PUBLIC tessesframework)
|
target_link_libraries(ttime PUBLIC tessesframework)
|
||||||
install(TARGETS ttime DESTINATION bin)
|
install(TARGETS ttime DESTINATION bin)
|
||||||
|
add_executable(tshell apps/tshell.cpp)
|
||||||
|
target_link_libraries(tshell PUBLIC tessesframework)
|
||||||
|
install(TARGETS tshell DESTINATION bin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(InstallRequiredSystemLibraries)
|
include(InstallRequiredSystemLibraries)
|
||||||
|
|||||||
90
CMakePresets.json
Normal file
90
CMakePresets.json
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"configurePresets": [
|
||||||
|
{
|
||||||
|
"name": "linux-debug",
|
||||||
|
"displayName": "Linux Debug",
|
||||||
|
"description": "Target the Windows Subsystem for Linux (WSL) or a remote Linux system.",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" },
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Linux"
|
||||||
|
},
|
||||||
|
"vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/2.0": { "remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "macos-debug",
|
||||||
|
"displayName": "macOS Debug",
|
||||||
|
"description": "Target a remote macOS system.",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" },
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Darwin"
|
||||||
|
},
|
||||||
|
"vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/1.0": { "sourceDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "windows-base",
|
||||||
|
"description": "Target Windows with the Visual Studio development environment.",
|
||||||
|
"hidden": true,
|
||||||
|
"generator": "Ninja",
|
||||||
|
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||||
|
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||||
|
"cacheVariables": {
|
||||||
|
"CMAKE_C_COMPILER": "cl.exe",
|
||||||
|
"CMAKE_CXX_COMPILER": "cl.exe",
|
||||||
|
"TESSESFRAMEWORK_ENABLE_MBED": false,
|
||||||
|
"TESSESFRAMEWORK_FETCHCONTENT": false
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "equals",
|
||||||
|
"lhs": "${hostSystemName}",
|
||||||
|
"rhs": "Windows"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-debug",
|
||||||
|
"displayName": "x64 Debug",
|
||||||
|
"description": "Target Windows (64-bit) with the Visual Studio development environment. (Debug)",
|
||||||
|
"inherits": "windows-base",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x64",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x64-release",
|
||||||
|
"displayName": "x64 Release",
|
||||||
|
"description": "Target Windows (64-bit) with the Visual Studio development environment. (RelWithDebInfo)",
|
||||||
|
"inherits": "x64-debug",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-debug",
|
||||||
|
"displayName": "x86 Debug",
|
||||||
|
"description": "Target Windows (32-bit) with the Visual Studio development environment. (Debug)",
|
||||||
|
"inherits": "windows-base",
|
||||||
|
"architecture": {
|
||||||
|
"value": "x86",
|
||||||
|
"strategy": "external"
|
||||||
|
},
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-release",
|
||||||
|
"displayName": "x86 Release",
|
||||||
|
"description": "Target Windows (32-bit) with the Visual Studio development environment. (RelWithDebInfo)",
|
||||||
|
"inherits": "x86-debug",
|
||||||
|
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,13 +1,16 @@
|
|||||||
Tesses Framework
|
Tesses Framework
|
||||||
================
|
================
|
||||||
|
|
||||||
|
## If you are on onedev
|
||||||
|
We are switching to [gitea](https://git.tesseslanguage.com/tesses50/tesses-framework)
|
||||||
|
|
||||||
## To Install
|
## To Install
|
||||||
- Install [mbedtls](https://github.com/Mbed-TLS/mbedtls) (use sudo apt install libmbedtls-dev on debian) for TessesFramework
|
- Install [mbedtls](https://github.com/Mbed-TLS/mbedtls) (use sudo apt install libmbedtls-dev on debian) for TessesFramework
|
||||||
- Follow the commands bellow
|
- Follow the commands bellow
|
||||||
|
|
||||||
## Run these commands to install tesses-framework
|
## Run these commands to install tesses-framework
|
||||||
```bash
|
```bash
|
||||||
git clone https://onedev.site.tesses.net/tesses-framework
|
git clone https://git.tesseslanguage.com/tesses-framework
|
||||||
cd tesses-framework
|
cd tesses-framework
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
|
|||||||
127
apps/tshell.cpp
Normal file
127
apps/tshell.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include "TessesFramework/TessesFramework.hpp"
|
||||||
|
#include "TessesFramework/Platform/Process.hpp"
|
||||||
|
using namespace Tesses::Framework;
|
||||||
|
using namespace Tesses::Framework::Platform;
|
||||||
|
using namespace Tesses::Framework::TextStreams;
|
||||||
|
using namespace Tesses::Framework::Filesystem;
|
||||||
|
|
||||||
|
void split_command(std::string cmd, std::vector<std::string>& args)
|
||||||
|
{
|
||||||
|
bool inStr=false;
|
||||||
|
std::string cur={};
|
||||||
|
auto flush=[&]()->void {
|
||||||
|
if(cur.empty()) return;
|
||||||
|
args.push_back(cur);
|
||||||
|
cur={};
|
||||||
|
};
|
||||||
|
for(size_t i = 0; i < cmd.size(); i++)
|
||||||
|
{
|
||||||
|
if(inStr)
|
||||||
|
{
|
||||||
|
if(cmd[i] == '\"') inStr=false;
|
||||||
|
else if(cmd[i] == '\\')
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if(i < cmd.size())
|
||||||
|
{
|
||||||
|
cmd.push_back(cmd[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else cur.push_back(cmd[i]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(cmd[i] == ' ') flush();
|
||||||
|
else if(cmd[i] == '\"') {
|
||||||
|
inStr=true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cur.push_back(cmd[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc,char** argv)
|
||||||
|
{
|
||||||
|
TF_Init();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
std::cout << VFSPath::GetAbsoluteCurrentDirectory().ToString() << "$ ";
|
||||||
|
|
||||||
|
|
||||||
|
std::string text;
|
||||||
|
StdIn().ReadLine(text);
|
||||||
|
std::vector<std::string> args;
|
||||||
|
split_command(text,args);
|
||||||
|
if(args.empty()) continue;
|
||||||
|
if(args[0] == "exit") break;
|
||||||
|
else if(args[0] == "echo") { if(args.size() > 1) std::cout << args[1] << std::endl;}
|
||||||
|
else if(args[0] == "cd") {
|
||||||
|
if(args.size() < 2)
|
||||||
|
{
|
||||||
|
VFSPath::SetAbsoluteCurrentDirectory(Environment::SpecialFolders::GetHomeFolder());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VFSPath::SetAbsoluteCurrentDirectory(args[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(args[0] == "printargs")
|
||||||
|
{
|
||||||
|
for(size_t i = 1; i < args.size(); i++)
|
||||||
|
{
|
||||||
|
std::cout << "\"" << Http::HttpUtils::Replace(args[i],"\"","\\\"") << "\"" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args[0] == "sigtermtest")
|
||||||
|
{
|
||||||
|
if (args.size() < 2) continue;
|
||||||
|
std::vector<std::string> args2(args.begin() + 1, args.end());
|
||||||
|
|
||||||
|
auto path = Environment::GetRealExecutablePath(args2[0]);
|
||||||
|
Platform::Process p(path.ToString(), args2);
|
||||||
|
if (p.Start())
|
||||||
|
{
|
||||||
|
std::cout << "Press enter to sigterm" << std::endl;
|
||||||
|
StdIn().ReadLine();
|
||||||
|
p.Kill(SIGTERM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(args[0] == "rstdi")
|
||||||
|
{
|
||||||
|
if(args.size()<3) continue;
|
||||||
|
std::vector<std::string> args2(args.begin()+2,args.end());
|
||||||
|
auto f = LocalFS.OpenFile(args[1],"rb");
|
||||||
|
if(f != nullptr)
|
||||||
|
{
|
||||||
|
auto path = Environment::GetRealExecutablePath(args2[0]);
|
||||||
|
Platform::Process p(path.ToString(),args2);
|
||||||
|
p.redirectStdIn=true;
|
||||||
|
if(p.Start())
|
||||||
|
{
|
||||||
|
auto strm = p.GetStdinStream();
|
||||||
|
f->CopyTo(strm);
|
||||||
|
delete strm;
|
||||||
|
p.CloseStdInNow();
|
||||||
|
p.WaitForExit();
|
||||||
|
}
|
||||||
|
delete f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto path = Environment::GetRealExecutablePath(args[0]);
|
||||||
|
Platform::Process p(path.ToString(),args);
|
||||||
|
if (p.Start())
|
||||||
|
p.WaitForExit();
|
||||||
|
else
|
||||||
|
std::cout << "Failed To Run Process: " << path.ToString() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TF_Quit();
|
||||||
|
}
|
||||||
@ -2,22 +2,43 @@
|
|||||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
|
||||||
#define SDL_MAIN_HANDLED
|
#define SDL_MAIN_HANDLED
|
||||||
|
#include "TessesFramework/Streams/MemoryStream.hpp"
|
||||||
|
#include "TessesFramework/Http/HttpClient.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Stream.hpp"
|
||||||
#include "TessesFramework/SDL2/GUI.hpp"
|
#include "TessesFramework/SDL2/GUI.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/ButtonView.hpp"
|
#include "TessesFramework/SDL2/Views/ButtonView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
|
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/LabelView.hpp"
|
#include "TessesFramework/SDL2/Views/LabelView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/TextListView.hpp"
|
#include "TessesFramework/SDL2/Views/ScrollableTextListView.hpp"
|
||||||
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
#include "TessesFramework/Filesystem/LocalFS.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/ProgressView.hpp"
|
#include "TessesFramework/SDL2/Views/ProgressView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/CheckView.hpp"
|
#include "TessesFramework/SDL2/Views/CheckView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
|
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/PictureView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/VScrollView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/HScrollView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/VStackView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/HStackView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/DropDownView.hpp"
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace Tesses::Framework;
|
using namespace Tesses::Framework;
|
||||||
using namespace Tesses::Framework::SDL2;
|
using namespace Tesses::Framework::SDL2;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void LoadImage(Views::PictureView& view)
|
||||||
|
{
|
||||||
|
using namespace Tesses::Framework::Streams;
|
||||||
|
using namespace Tesses::Framework::Http;
|
||||||
|
MemoryStream strm(true);
|
||||||
|
|
||||||
|
DownloadToStreamSimple("https://s.ytimg.com/vi/lItUxNQnzME/maxresdefault.jpg",strm);
|
||||||
|
strm.Seek(0L,SeekOrigin::Begin);
|
||||||
|
auto res = RwopsFromStream(&strm,false);
|
||||||
|
view.SetPicture(IMG_Load_RW(res,1),true);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc,char** argv)
|
int main(int argc,char** argv)
|
||||||
{
|
{
|
||||||
@ -25,6 +46,9 @@ int main(int argc,char** argv)
|
|||||||
|
|
||||||
TF_Init();
|
TF_Init();
|
||||||
|
|
||||||
|
//std::cout << GUI_EXPAND_N(argc) << std::endl;
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::pair<SDL_Color,std::string>> colors={
|
std::vector<std::pair<SDL_Color,std::string>> colors={
|
||||||
std::pair<SDL_Color,std::string>({.r=255,.g=0,.b=128,.a=255},"Magenta"),
|
std::pair<SDL_Color,std::string>({.r=255,.g=0,.b=128,.a=255},"Magenta"),
|
||||||
std::pair<SDL_Color,std::string>({.r=255,.g=0,.b=0,.a=255}, "Red"),
|
std::pair<SDL_Color,std::string>({.r=255,.g=0,.b=0,.a=255}, "Red"),
|
||||||
@ -38,23 +62,36 @@ int main(int argc,char** argv)
|
|||||||
bool darkMode=true;
|
bool darkMode=true;
|
||||||
size_t color_index=0;
|
size_t color_index=0;
|
||||||
|
|
||||||
GUIPalette pal0(darkMode,colors[color_index % colors.size()].first,20);
|
|
||||||
|
GUIPalette pal0(darkMode,colors[color_index % colors.size()].first,20,2);
|
||||||
TF_LOG("Create pallete");
|
TF_LOG("Create pallete");
|
||||||
GUIWindow window("My Window Title",1280,720,SDL_WINDOW_RESIZABLE,pal0);
|
GUIWindow* window = new GUIWindow("My Window Title",1280,720,SDL_WINDOW_RESIZABLE,pal0);
|
||||||
TF_LOG("Created GUIWindow success");
|
TF_LOG("Created GUIWindow success");
|
||||||
|
|
||||||
Views::LabelView lbl("A random label\nThat spans lines.");
|
Views::LabelView lbl("A random label\nThat spans lines.");
|
||||||
|
|
||||||
Views::ButtonView btn("Dark Mode");
|
Views::ButtonView btn("Dark Mode");
|
||||||
Views::ButtonView btn2(colors[0].second);
|
Views::ButtonView btn2(colors[0].second);
|
||||||
|
Views::ButtonView btn3("Popup");
|
||||||
|
Views::ButtonView btn4("Window");
|
||||||
Views::ProgressView progress(42.42);
|
Views::ProgressView progress(42.42);
|
||||||
|
|
||||||
Views::CheckView cv(false,"Checkbox");
|
Views::CheckView cv(false,"Checkbox");
|
||||||
Views::CheckView cv2(false,"Another Checkbox");
|
Views::CheckView cv2(false,"Another Checkbox");
|
||||||
Views::EditTextView edit("Enter some text");
|
Views::EditTextView edit("Enter some text");
|
||||||
|
Views::DropDownView ddv;
|
||||||
|
ddv.GetItems()={
|
||||||
|
"Al Gore",
|
||||||
|
"Demi Lovato",
|
||||||
|
"Steve Ballmer"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Views::TextListView list;
|
Views::ScrollableTextListView list;
|
||||||
|
for(int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
list.items.push_back(std::to_string(i));
|
||||||
|
}
|
||||||
/*for(auto item : Tesses::Framework::Filesystem::LocalFS.EnumeratePaths((std::string)"/usr/bin"))
|
/*for(auto item : Tesses::Framework::Filesystem::LocalFS.EnumeratePaths((std::string)"/usr/bin"))
|
||||||
{
|
{
|
||||||
list.items.push_back(item.GetFileName());
|
list.items.push_back(item.GetFileName());
|
||||||
@ -80,8 +117,49 @@ int main(int argc,char** argv)
|
|||||||
|
|
||||||
abs.Add({.x=32,.y=478,.w=300,.h=200},&edit,false);
|
abs.Add({.x=32,.y=478,.w=300,.h=200},&edit,false);
|
||||||
|
|
||||||
window.SetView(&abs,false);
|
Views::VScrollView vscroll(0,0,10);
|
||||||
window.SDLEvent += std::make_shared<FunctionalEvent<View*,GUISDLEventEventArgs&>>([&window,&lbl](View* sender, GUISDLEventEventArgs& e)->void {
|
Views::HScrollView hscroll(0,0,10);
|
||||||
|
|
||||||
|
Views::LabelView lbl2("ScrollPos");
|
||||||
|
|
||||||
|
vscroll.ValueChanged += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>(
|
||||||
|
[&](View* sender,GUIEventArgs& e)->void {
|
||||||
|
lbl2.SetText("ScrollPos: " + std::to_string(vscroll.value));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Views::PictureView img;
|
||||||
|
LoadImage(img);
|
||||||
|
|
||||||
|
abs.Add({.x=460,.y=32,.w=640,.h=480},&img,false);
|
||||||
|
|
||||||
|
abs.Add({.x=1280-42,.y=2,.w=32,.h=720-20},&vscroll,false);
|
||||||
|
|
||||||
|
abs.Add({.x=720,.y=720-100,.w=200,.h=100},&lbl2,false);
|
||||||
|
|
||||||
|
|
||||||
|
Views::VStackView vstack;
|
||||||
|
vstack.Add(GUI_MIN,&edit,false);
|
||||||
|
vstack.Add(GUI_MIN,&btn3,false);
|
||||||
|
vstack.Add(32,&ddv,false);
|
||||||
|
vstack.Add(GUI_MIN,&btn4,false);
|
||||||
|
|
||||||
|
vstack.Add(GUI_EXPAND,&btn,false);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vstack.Add(GUI_EXPAND_N(10),&list,false);
|
||||||
|
vstack.Add(GUI_EXPAND,&btn2,false);
|
||||||
|
|
||||||
|
vstack.Add(GUI_MIN,&hscroll,false);
|
||||||
|
|
||||||
|
Views::HStackView hstack;
|
||||||
|
hstack.Add(GUI_EXPAND,&vstack,false);
|
||||||
|
hstack.Add(GUI_MIN,&vscroll,false);
|
||||||
|
|
||||||
|
window->SetView(&hstack,false);
|
||||||
|
//window.SetView(&abs,false);
|
||||||
|
window->SDLEvent += std::make_shared<FunctionalEvent<View*,GUISDLEventEventArgs&>>([&window,&lbl](View* sender, GUISDLEventEventArgs& e)->void {
|
||||||
std::string sdl2_event = "SDL_Event: " + std::to_string(e.event.type);
|
std::string sdl2_event = "SDL_Event: " + std::to_string(e.event.type);
|
||||||
TF_LOG(sdl2_event);
|
TF_LOG(sdl2_event);
|
||||||
if(e.event.type == SDL_EventType::SDL_WINDOWEVENT)
|
if(e.event.type == SDL_EventType::SDL_WINDOWEVENT)
|
||||||
@ -98,7 +176,7 @@ int main(int argc,char** argv)
|
|||||||
darkMode = !darkMode;
|
darkMode = !darkMode;
|
||||||
btn.SetText(darkMode ? "Light Mode" : "Dark Mode");
|
btn.SetText(darkMode ? "Light Mode" : "Dark Mode");
|
||||||
GUIPalette palette(darkMode,colors[color_index % colors.size()].first,20);
|
GUIPalette palette(darkMode,colors[color_index % colors.size()].first,20);
|
||||||
window.SetPalette(palette);
|
window->SetPalette(palette);
|
||||||
});
|
});
|
||||||
//"A random label\nThat spans lines."
|
//"A random label\nThat spans lines."
|
||||||
|
|
||||||
@ -107,9 +185,23 @@ int main(int argc,char** argv)
|
|||||||
btn2.SetText(colors[color_index % colors.size()].second);
|
btn2.SetText(colors[color_index % colors.size()].second);
|
||||||
|
|
||||||
GUIPalette palette(darkMode,colors[color_index % colors.size()].first,20);
|
GUIPalette palette(darkMode,colors[color_index % colors.size()].first,20);
|
||||||
window.SetPalette(palette);
|
window->SetPalette(palette);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Views::LabelView lbl3;
|
||||||
|
|
||||||
|
GUIContainerPopup popup(42,42,300,200);
|
||||||
|
popup.SetView(&lbl3,false);
|
||||||
|
|
||||||
|
btn3.Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&](View* sender, GUIEventArgs& e)->void{
|
||||||
|
lbl3.SetText(edit.GetText());
|
||||||
|
window->ShowPopup(popup);
|
||||||
|
});
|
||||||
|
|
||||||
|
//window("My Window Title",1280,720,SDL_WINDOW_RESIZABLE,pal0);
|
||||||
|
btn4.Click += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([&](View* sender, GUIEventArgs& e)->void{
|
||||||
|
new GUIWindow("My Second Window",640,480,0,pal0);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
TF_RunEventLoop();
|
TF_RunEventLoop();
|
||||||
|
|||||||
@ -112,6 +112,7 @@ namespace Tesses::Framework
|
|||||||
bool TF_GetConsoleEventsEnabled();
|
bool TF_GetConsoleEventsEnabled();
|
||||||
void TF_SetConsoleEventsEnabled(bool flag);
|
void TF_SetConsoleEventsEnabled(bool flag);
|
||||||
void TF_InitConsole();
|
void TF_InitConsole();
|
||||||
|
void TF_Invoke(std::function<void()> cb);
|
||||||
|
|
||||||
#if defined(TESSESFRAMEWORK_LOGTOFILE)
|
#if defined(TESSESFRAMEWORK_LOGTOFILE)
|
||||||
void TF_Log(std::string dataToLog);
|
void TF_Log(std::string dataToLog);
|
||||||
|
|||||||
@ -1,26 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "TessesFramework/Streams/Stream.hpp"
|
#include "TessesFramework/Streams/Stream.hpp"
|
||||||
#include "TessesFramework/HiddenField.hpp"
|
#include "TessesFramework/HiddenField.hpp"
|
||||||
|
#include <signal.h>
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define SIGKILL 9
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Tesses::Framework::Platform {
|
namespace Tesses::Framework::Platform {
|
||||||
class Process {
|
class Process {
|
||||||
private:
|
private:
|
||||||
HiddenField hidden;
|
HiddenField hidden;
|
||||||
|
bool exited = false;
|
||||||
|
int exitCode=0;
|
||||||
public:
|
public:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
std::string workingDirectory;
|
||||||
std::vector<std::pair<std::string,std::string>> env;
|
std::vector<std::pair<std::string,std::string>> env;
|
||||||
bool includeThisEnv;
|
bool includeThisEnv;
|
||||||
bool redirectStdIn=false;
|
bool redirectStdIn=false;
|
||||||
bool redirectStdOut=false;
|
bool redirectStdOut=false;
|
||||||
bool redirectStdErr=false;
|
bool redirectStdErr=false;
|
||||||
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
|
bool HasExited();
|
||||||
Tesses::Framework::Streams::Stream* GetStdinStream(bool closeUnderlying=true);
|
|
||||||
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
|
|
||||||
Tesses::Framework::Streams::Stream* GetStdoutStream(bool closeUnderlying=true);
|
void CloseStdInNow();
|
||||||
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM
|
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT
|
||||||
Tesses::Framework::Streams::Stream* GetStderrStream(bool closeUnderlying=true);
|
|
||||||
|
Tesses::Framework::Streams::Stream* GetStdinStream();
|
||||||
|
|
||||||
|
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT
|
||||||
|
Tesses::Framework::Streams::Stream* GetStdoutStream();
|
||||||
|
//YOU ARE RESPONSABLE FOR FREEING THIS STREAM OBJECT
|
||||||
|
Tesses::Framework::Streams::Stream* GetStderrStream();
|
||||||
|
|
||||||
Process();
|
Process();
|
||||||
Process(std::string name, std::vector<std::string> args,bool includeThisEnv=true);
|
Process(std::string name, std::vector<std::string> args,bool includeThisEnv=true);
|
||||||
|
|||||||
@ -12,15 +12,16 @@ namespace Tesses::Framework::SDL2
|
|||||||
class GUIPalette {
|
class GUIPalette {
|
||||||
public:
|
public:
|
||||||
GUIPalette();
|
GUIPalette();
|
||||||
GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize=24);
|
GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize=24,int borderSize=2);
|
||||||
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=24);
|
GUIPalette(SDL_Color accent, SDL_Color background, SDL_Color borderColor, SDL_Color borderHover, SDL_Color borderActive, SDL_Color borderHoverActive, int fontSize=24,int borderSize=2);
|
||||||
SDL_Color accent; //color is used for font when not over accent background
|
SDL_Color accent; //color is used for font when not over accent background
|
||||||
SDL_Color background;
|
SDL_Color background;
|
||||||
SDL_Color border_color; //color is used for font when over accent background
|
SDL_Color borderColor; //color is used for font when over accent background
|
||||||
SDL_Color border_hover;
|
SDL_Color borderHover;
|
||||||
SDL_Color border_active;
|
SDL_Color borderActive;
|
||||||
SDL_Color border_hover_active;
|
SDL_Color borderHoverActive;
|
||||||
int fontSize;
|
int fontSize;
|
||||||
|
int borderSize;
|
||||||
|
|
||||||
SDL_Color& GetBorderColor(bool isHovering, bool isActive, bool isMouseDown);
|
SDL_Color& GetBorderColor(bool isHovering, bool isActive, bool isMouseDown);
|
||||||
};
|
};
|
||||||
@ -32,6 +33,12 @@ namespace Tesses::Framework::SDL2
|
|||||||
virtual ~GUIEventArgs();
|
virtual ~GUIEventArgs();
|
||||||
};
|
};
|
||||||
class View;
|
class View;
|
||||||
|
class GUIWindowClosingEventArgs : public GUIEventArgs
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool cancel;
|
||||||
|
std::string Type();
|
||||||
|
};
|
||||||
class GUIMouseButtonEventArgs : public GUIEventArgs
|
class GUIMouseButtonEventArgs : public GUIEventArgs
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -62,6 +69,22 @@ namespace Tesses::Framework::SDL2
|
|||||||
constexpr uint64_t VIEWFLAG_INTERCEPT_TAB=(uint64_t)1<<4;
|
constexpr uint64_t VIEWFLAG_INTERCEPT_TAB=(uint64_t)1<<4;
|
||||||
constexpr uint64_t VIEWFLAG_CHECKED=(uint64_t)1<<5;
|
constexpr uint64_t VIEWFLAG_CHECKED=(uint64_t)1<<5;
|
||||||
constexpr uint64_t VIEWFLAG_TOUCHED=(uint64_t)1<<6;
|
constexpr uint64_t VIEWFLAG_TOUCHED=(uint64_t)1<<6;
|
||||||
|
constexpr uint64_t VIEWFLAG_HOVER_B1STATE=(uint64_t)1<<7; //for scrollbar buttons
|
||||||
|
constexpr uint64_t VIEWFLAG_HOVER_B2STATE=(uint64_t)1<<8; //for scrollbar buttons
|
||||||
|
constexpr uint64_t VIEWFLAG_MOUSEDOWN_B1STATE=(uint64_t)1<<9; //for scrollbar buttons
|
||||||
|
constexpr uint64_t VIEWFLAG_MOUSEDOWN_B2STATE=(uint64_t)1<<10; //for scrollbar buttons
|
||||||
|
|
||||||
|
constexpr int GUI_EXPAND = -1;
|
||||||
|
constexpr int GUI_MIN = 0;
|
||||||
|
|
||||||
|
|
||||||
|
constexpr int GUI_EXPAND_N(int n)
|
||||||
|
{
|
||||||
|
if(n < 0) return n;
|
||||||
|
return -n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class GUIPopup;
|
class GUIPopup;
|
||||||
class GUIWindow;
|
class GUIWindow;
|
||||||
class ContainerView;
|
class ContainerView;
|
||||||
@ -161,25 +184,71 @@ namespace Tesses::Framework::SDL2
|
|||||||
Done
|
Done
|
||||||
};
|
};
|
||||||
class GUIPopup : public ContainerView {
|
class GUIPopup : public ContainerView {
|
||||||
View* child;
|
|
||||||
bool ownsChild;
|
|
||||||
protected:
|
protected:
|
||||||
void OnDraw(SDL_Renderer* renderer, SDL_Rect& myRect);
|
bool closed=true;
|
||||||
bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
virtual View* GetView()=0;
|
||||||
public:
|
|
||||||
|
|
||||||
size_t ViewCount();
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& myRect);
|
||||||
View* GetViewAt(size_t index);
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
GUIPopup();
|
GUIPopup();
|
||||||
GUIPopup(SDL_Rect bounds);
|
GUIPopup(SDL_Rect bounds);
|
||||||
GUIPopup(int x, int y,int w, int h);
|
GUIPopup(int x, int y,int w, int h);
|
||||||
SDL_Rect bounds;
|
SDL_Rect bounds;
|
||||||
|
bool closeIfClickOutside=true;
|
||||||
|
|
||||||
void SetView(View* view, bool owns=true);
|
virtual void Close();
|
||||||
~GUIPopup();
|
virtual bool IsClosed();
|
||||||
|
virtual ~GUIPopup();
|
||||||
|
|
||||||
|
size_t ViewCount();
|
||||||
|
View* GetViewAt(size_t index);
|
||||||
|
|
||||||
|
bool IsActive();
|
||||||
|
|
||||||
friend class GUIWindow;
|
friend class GUIWindow;
|
||||||
};
|
};
|
||||||
|
class GUIContainerPopup : public GUIPopup
|
||||||
|
{
|
||||||
|
View* child;
|
||||||
|
bool ownsChild;
|
||||||
|
protected:
|
||||||
|
View* GetView();
|
||||||
|
public:
|
||||||
|
GUIContainerPopup();
|
||||||
|
GUIContainerPopup(SDL_Rect bounds);
|
||||||
|
GUIContainerPopup(int x, int y,int w, int h);
|
||||||
|
|
||||||
|
void SetView(View* view, bool owns=true);
|
||||||
|
|
||||||
|
~GUIContainerPopup();
|
||||||
|
};
|
||||||
|
class GUIDialog : public GUIPopup {
|
||||||
|
protected:
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& myRect);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
GUIDialog();
|
||||||
|
GUIDialog(SDL_Rect bounds);
|
||||||
|
GUIDialog(int x,int y, int w, int h);
|
||||||
|
virtual ~GUIDialog();
|
||||||
|
};
|
||||||
|
class GUIContainerDialog : public GUIDialog
|
||||||
|
{
|
||||||
|
View* v;
|
||||||
|
bool owns=false;
|
||||||
|
protected:
|
||||||
|
View* GetView();
|
||||||
|
public:
|
||||||
|
GUIContainerDialog();
|
||||||
|
GUIContainerDialog(SDL_Rect bounds);
|
||||||
|
GUIContainerDialog(int x, int y,int w, int h);
|
||||||
|
void SetView(View* view, bool owns=true);
|
||||||
|
size_t ViewCount();
|
||||||
|
View* GetViewAt(size_t index);
|
||||||
|
~GUIContainerDialog();
|
||||||
|
};
|
||||||
|
|
||||||
class GUIWindow : public ContainerView
|
class GUIWindow : public ContainerView
|
||||||
{
|
{
|
||||||
std::vector<GUIPopup*> popups;
|
std::vector<GUIPopup*> popups;
|
||||||
@ -198,6 +267,7 @@ namespace Tesses::Framework::SDL2
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
EventList<View*,GUIJsonViewNotFoundEventArgs&> JsonViewNotFound;
|
EventList<View*,GUIJsonViewNotFoundEventArgs&> JsonViewNotFound;
|
||||||
|
EventList<View*,GUIWindowClosingEventArgs&> Closing;
|
||||||
size_t ViewCount();
|
size_t ViewCount();
|
||||||
View* GetViewAt(size_t index);
|
View* GetViewAt(size_t index);
|
||||||
FontCache* normal_font;
|
FontCache* normal_font;
|
||||||
@ -228,6 +298,7 @@ namespace Tesses::Framework::SDL2
|
|||||||
SDL_Renderer* GetSDLRenderer();
|
SDL_Renderer* GetSDLRenderer();
|
||||||
|
|
||||||
View* CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json);
|
View* CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json);
|
||||||
|
operator bool();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -235,6 +306,7 @@ namespace Tesses::Framework::SDL2
|
|||||||
std::vector<GUIWindow*> windows;
|
std::vector<GUIWindow*> windows;
|
||||||
public:
|
public:
|
||||||
void Update();
|
void Update();
|
||||||
|
void CloseWindows();
|
||||||
friend class GUIWindow;
|
friend class GUIWindow;
|
||||||
};
|
};
|
||||||
extern GUI gui;
|
extern GUI gui;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
public:
|
public:
|
||||||
ButtonView();
|
ButtonView();
|
||||||
ButtonView(std::string text);
|
ButtonView(std::string text);
|
||||||
|
virtual std::pair<int,int> PreferedMinSize();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
23
include/TessesFramework/SDL2/Views/DropDownView.hpp
Normal file
23
include/TessesFramework/SDL2/Views/DropDownView.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
#include "ScrollableTextListView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class DropDownView : public View {
|
||||||
|
|
||||||
|
GUIContainerPopup popup;
|
||||||
|
ScrollableTextListView listView;
|
||||||
|
bool hasSet=false;
|
||||||
|
protected:
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
DropDownView();
|
||||||
|
std::vector<std::string>& GetItems();
|
||||||
|
void SetIndex(int index);
|
||||||
|
int GetIndex();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
24
include/TessesFramework/SDL2/Views/HScrollView.hpp
Normal file
24
include/TessesFramework/SDL2/Views/HScrollView.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class HScrollView : public View {
|
||||||
|
protected:
|
||||||
|
virtual void OnValueChanged(GUIEventArgs& e);
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
HScrollView();
|
||||||
|
HScrollView(uint64_t value, uint64_t min, uint64_t max,uint64_t step=1);
|
||||||
|
uint64_t value;
|
||||||
|
uint64_t min;
|
||||||
|
uint64_t max;
|
||||||
|
uint64_t step;
|
||||||
|
EventList<View*,GUIEventArgs&> ValueChanged;
|
||||||
|
|
||||||
|
std::pair<int,int> PreferedMinSize();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
27
include/TessesFramework/SDL2/Views/HStackView.hpp
Normal file
27
include/TessesFramework/SDL2/Views/HStackView.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class HStackView : public ContainerView {
|
||||||
|
|
||||||
|
std::vector<std::pair<int,std::pair<View*,bool>>> items;
|
||||||
|
protected:
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
HStackView();
|
||||||
|
int spacing=0;
|
||||||
|
|
||||||
|
void Add(int sz, View* view, bool owns=true);
|
||||||
|
void Remove(View* view);
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
virtual size_t ViewCount();
|
||||||
|
virtual View* GetViewAt(size_t index);
|
||||||
|
|
||||||
|
virtual ~HStackView();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
27
include/TessesFramework/SDL2/Views/MultilineEditTextView.hpp
Normal file
27
include/TessesFramework/SDL2/Views/MultilineEditTextView.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class MultilineEditTextView : public View {
|
||||||
|
protected:
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
std::string hint;
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
SDL_Point topLeft={.x=0,.y=0};
|
||||||
|
SDL_Point cursorPos={.x=0,.y=0};
|
||||||
|
SDL_Point cursorEnd={.x=-1,.y=-1};
|
||||||
|
public:
|
||||||
|
MultilineEditTextView();
|
||||||
|
MultilineEditTextView(std::string hint);
|
||||||
|
virtual std::string GetHint();
|
||||||
|
virtual void SetHint(std::string hint);
|
||||||
|
virtual std::string GetText();
|
||||||
|
virtual void SetText(std::string text);
|
||||||
|
virtual void TypeText(std::string text);
|
||||||
|
virtual std::pair<int,int> PreferedMinSize();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class ScrollableTextListView : public View {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
ScrollableTextListView();
|
||||||
|
size_t firstIndex;
|
||||||
|
int selected;
|
||||||
|
std::vector<std::string> items;
|
||||||
|
|
||||||
|
EventList<View*,GUIEventArgs&> ValueChanged;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -15,6 +15,7 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
int selected;
|
int selected;
|
||||||
std::vector<std::string> items;
|
std::vector<std::string> items;
|
||||||
|
|
||||||
|
EventList<View*,GUIEventArgs&> ValueChanged;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
24
include/TessesFramework/SDL2/Views/VScrollView.hpp
Normal file
24
include/TessesFramework/SDL2/Views/VScrollView.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class VScrollView : public View {
|
||||||
|
protected:
|
||||||
|
virtual void OnValueChanged(GUIEventArgs& e);
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
VScrollView();
|
||||||
|
VScrollView(uint64_t value, uint64_t min, uint64_t max,uint64_t step=1);
|
||||||
|
uint64_t value;
|
||||||
|
uint64_t min;
|
||||||
|
uint64_t max;
|
||||||
|
uint64_t step;
|
||||||
|
EventList<View*,GUIEventArgs&> ValueChanged;
|
||||||
|
|
||||||
|
std::pair<int,int> PreferedMinSize();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
29
include/TessesFramework/SDL2/Views/VStackView.hpp
Normal file
29
include/TessesFramework/SDL2/Views/VStackView.hpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "../GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
class VStackView : public ContainerView {
|
||||||
|
|
||||||
|
std::vector<std::pair<int,std::pair<View*,bool>>> items;
|
||||||
|
protected:
|
||||||
|
virtual void OnDraw(SDL_Renderer* renderer, SDL_Rect& r);
|
||||||
|
virtual bool OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds);
|
||||||
|
public:
|
||||||
|
VStackView();
|
||||||
|
int spacing=0;
|
||||||
|
|
||||||
|
void Add(int sz, View* view, bool owns=true);
|
||||||
|
void Remove(View* view);
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
virtual size_t ViewCount();
|
||||||
|
virtual View* GetViewAt(size_t index);
|
||||||
|
|
||||||
|
virtual ~VStackView();
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -18,6 +18,7 @@
|
|||||||
#include "TextStreams/StdIOWriter.hpp"
|
#include "TextStreams/StdIOWriter.hpp"
|
||||||
#include "TextStreams/StringReader.hpp"
|
#include "TextStreams/StringReader.hpp"
|
||||||
#include "TextStreams/StringWriter.hpp"
|
#include "TextStreams/StringWriter.hpp"
|
||||||
|
#include "Text/StringConverter.hpp"
|
||||||
#include "Threading/Thread.hpp"
|
#include "Threading/Thread.hpp"
|
||||||
#include "Threading/Mutex.hpp"
|
#include "Threading/Mutex.hpp"
|
||||||
#include "Threading/ThreadPool.hpp"
|
#include "Threading/ThreadPool.hpp"
|
||||||
@ -34,6 +35,8 @@
|
|||||||
#include "Serialization/Json.hpp"
|
#include "Serialization/Json.hpp"
|
||||||
#include "Serialization/SQLite.hpp"
|
#include "Serialization/SQLite.hpp"
|
||||||
#include "Platform/Environment.hpp"
|
#include "Platform/Environment.hpp"
|
||||||
|
#include "Platform/Process.hpp"
|
||||||
|
#include "Text/StringConverter.hpp"
|
||||||
#include "SDL2/FontCache.hpp"
|
#include "SDL2/FontCache.hpp"
|
||||||
#include "SDL2/Stream.hpp"
|
#include "SDL2/Stream.hpp"
|
||||||
#include "SDL2/GUI.hpp"
|
#include "SDL2/GUI.hpp"
|
||||||
20
include/TessesFramework/Text/StringConverter.hpp
Normal file
20
include/TessesFramework/Text/StringConverter.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
namespace Tesses::Framework::Text::StringConverter {
|
||||||
|
class UTF8 {
|
||||||
|
public:
|
||||||
|
static void FromUTF16(std::basic_string<char>& utf8, const std::basic_string<char16_t>& utf16);
|
||||||
|
static void FromUTF32(std::basic_string<char>& utf8, const std::basic_string<char32_t>& utf32);
|
||||||
|
};
|
||||||
|
class UTF16 {
|
||||||
|
public:
|
||||||
|
static void FromUTF8(std::basic_string<char16_t>& utf16, const std::basic_string<char>& utf8);
|
||||||
|
static void FromUTF32(std::basic_string<char16_t>& utf16, const std::basic_string<char32_t>& utf32);
|
||||||
|
};
|
||||||
|
class UTF32 {
|
||||||
|
public:
|
||||||
|
static void FromUTF8(std::basic_string<char32_t>& utf32, const std::basic_string<char>& utf8);
|
||||||
|
static void FromUTF16(std::basic_string<char32_t>& utf32, const std::basic_string<char16_t>& utf16);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -208,6 +208,7 @@ namespace Tesses::Framework::Filesystem
|
|||||||
}
|
}
|
||||||
VFSPath VFSPath::MakeAbsolute(VFSPath curDir)
|
VFSPath VFSPath::MakeAbsolute(VFSPath curDir)
|
||||||
{
|
{
|
||||||
|
if (!this->relative) return *this;
|
||||||
VFSPath p2 = curDir / *this;
|
VFSPath p2 = curDir / *this;
|
||||||
return p2.CollapseRelativeParents();
|
return p2.CollapseRelativeParents();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||||
|
#include "TessesFramework/Text/StringConverter.hpp"
|
||||||
|
|
||||||
|
using namespace Tesses::Framework::Text::StringConverter;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
extern char** environ;
|
extern char** environ;
|
||||||
@ -118,7 +122,8 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
{
|
{
|
||||||
using namespace Tesses::Framework::Http;
|
using namespace Tesses::Framework::Http;
|
||||||
|
|
||||||
if(!realPath.relative) return realPath.MakeAbsolute();
|
|
||||||
|
if(!realPath.relative) return realPath;
|
||||||
if(LocalFS.FileExists(realPath)) return realPath.MakeAbsolute();
|
if(LocalFS.FileExists(realPath)) return realPath.MakeAbsolute();
|
||||||
const char* path = std::getenv("PATH");
|
const char* path = std::getenv("PATH");
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@ -128,12 +133,13 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
auto pathParts = HttpUtils::SplitString(path,";");
|
auto pathParts = HttpUtils::SplitString(path,";");
|
||||||
for(auto item : pathParts)
|
for(auto item : pathParts)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
|
||||||
for(auto item2 : pext)
|
for(auto item2 : pext)
|
||||||
{
|
{
|
||||||
auto newPathExt = newPath + item2;
|
auto newPathExt = newPath + item2;
|
||||||
if(LocalFS.FileExists(newPathExt)) return newPathExt;
|
if(LocalFS.FileExists(newPathExt)) return newPathExt;
|
||||||
}
|
}
|
||||||
auto newPath = LocalFS.SystemToVFSPath(item) / realPath;
|
|
||||||
if(LocalFS.FileExists(newPath)) return newPath;
|
if(LocalFS.FileExists(newPath)) return newPath;
|
||||||
}
|
}
|
||||||
return realPath;
|
return realPath;
|
||||||
@ -158,16 +164,28 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
}
|
}
|
||||||
void SetVariable(std::string name, std::optional<std::string> var)
|
void SetVariable(std::string name, std::optional<std::string> var)
|
||||||
{
|
{
|
||||||
if(var)
|
if (var)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
SetEnvironmentVariable(name.c_str(),var->c_str());
|
{
|
||||||
|
std::u16string nameu16 = {};
|
||||||
|
|
||||||
|
std::u16string varu16 = {};
|
||||||
|
|
||||||
|
UTF16::FromUTF8(nameu16, name);
|
||||||
|
UTF16::FromUTF8(varu16, var.value());
|
||||||
|
SetEnvironmentVariableW((LPCWSTR)nameu16.c_str(),(LPCWSTR)varu16.c_str());
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
setenv(name.c_str(), var->c_str(),1);
|
setenv(name.c_str(), var->c_str(),1);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
{
|
{
|
||||||
SetEnvironmentVariable(name.c_str(),NULL);
|
std::u16string nameu16 = {};
|
||||||
|
|
||||||
|
UTF16::FromUTF8(nameu16, name);
|
||||||
|
|
||||||
|
SetEnvironmentVariableW((LPCWSTR)nameu16.c_str(),NULL);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
unsetenv(name.c_str());
|
unsetenv(name.c_str());
|
||||||
@ -179,11 +197,14 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env)
|
void GetEnvironmentVariables(std::vector<std::pair<std::string,std::string>>& env)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
char *environ0 = GetEnvironmentStrings();
|
auto environ0 = GetEnvironmentStringsW();
|
||||||
char* envthing = environ0;
|
auto envthing = environ0;
|
||||||
while(*envthing)
|
while(*envthing)
|
||||||
{
|
{
|
||||||
auto items = Http::HttpUtils::SplitString(envthing,"=",2);
|
std::u16string str = (const char16_t*)envthing;
|
||||||
|
std::string stru8;
|
||||||
|
UTF8::FromUTF16(stru8, str);
|
||||||
|
auto items = Http::HttpUtils::SplitString(stru8, "=", 2);
|
||||||
if(items.size() == 2)
|
if(items.size() == 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -193,13 +214,13 @@ namespace Tesses::Framework::Platform::Environment
|
|||||||
{
|
{
|
||||||
env.push_back(std::pair<std::string,std::string>(items[0],""));
|
env.push_back(std::pair<std::string,std::string>(items[0],""));
|
||||||
}
|
}
|
||||||
envthing += strlen(envthing)+1;
|
envthing += str.size() + 1;
|
||||||
}
|
}
|
||||||
FreeEnvironmentStrings(environ0);
|
FreeEnvironmentStringsW(environ0);
|
||||||
#else
|
#else
|
||||||
for(char** envthing = environ; envthing != NULL; envthing++)
|
for(char** envthing = environ; *envthing != NULL; envthing++)
|
||||||
{
|
{
|
||||||
|
//if(*envthing == NULL) break;
|
||||||
auto items = Http::HttpUtils::SplitString(*envthing,"=",2);
|
auto items = Http::HttpUtils::SplitString(*envthing,"=",2);
|
||||||
if(items.size() == 2)
|
if(items.size() == 2)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,18 +1,78 @@
|
|||||||
#include "TessesFramework/Platform/Process.hpp"
|
#include "TessesFramework/Platform/Process.hpp"
|
||||||
#include "TessesFramework/Http/HttpUtils.hpp"
|
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||||
#include "TessesFramework/Platform/Environment.hpp"
|
#include "TessesFramework/Platform/Environment.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
extern "C" {
|
||||||
|
#include <windows.h>
|
||||||
|
}
|
||||||
|
#include "TessesFramework/Filesystem/VFSFix.hpp"
|
||||||
|
#include "TessesFramework/Text/StringConverter.hpp"
|
||||||
|
using namespace Tesses::Framework::Text::StringConverter;
|
||||||
|
static void escape_windows_args(std::string& str, std::vector<std::string> args)
|
||||||
|
{
|
||||||
|
bool first = true;
|
||||||
|
for (auto item : args)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
str.push_back('\"');
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str.append(" \"");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto c : item)
|
||||||
|
{
|
||||||
|
if (c == '"') str.append("\\\"");
|
||||||
|
else str.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
str.push_back('\"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Tesses::Framework::Platform {
|
namespace Tesses::Framework::Platform {
|
||||||
|
|
||||||
class ProcessData {
|
class ProcessData : public HiddenFieldData {
|
||||||
public:
|
public:
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
STARTUPINFOW si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
HANDLE stdin_strm;
|
||||||
|
HANDLE stdout_strm;
|
||||||
|
HANDLE stderr_strm;
|
||||||
|
|
||||||
|
static int __stdcall KillGraceFully(HWND hndle, LPARAM arg)
|
||||||
|
{
|
||||||
|
auto pd=static_cast<ProcessData*>((void*)arg);
|
||||||
|
DWORD curProc;
|
||||||
|
GetWindowThreadProcessId(hndle, &curProc);
|
||||||
|
if (curProc == pd->pi.dwProcessId)
|
||||||
|
{
|
||||||
|
PostMessage(hndle, WM_CLOSE, 0, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
#else
|
#else
|
||||||
int stdin_strm;
|
int stdin_strm;
|
||||||
@ -20,9 +80,16 @@ namespace Tesses::Framework::Platform {
|
|||||||
int stderr_strm;
|
int stderr_strm;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ProcessData() {
|
ProcessData() {
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
stdin_strm = NULL;
|
||||||
|
stdout_strm = NULL;
|
||||||
|
stderr_strm = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
|
|
||||||
@ -35,23 +102,30 @@ namespace Tesses::Framework::Platform {
|
|||||||
};
|
};
|
||||||
class ProcessStream : public Tesses::Framework::Streams::Stream {
|
class ProcessStream : public Tesses::Framework::Streams::Stream {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
HANDLE strm;
|
||||||
|
bool writing;
|
||||||
|
bool eos;
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
#else
|
#else
|
||||||
int strm;
|
int strm;
|
||||||
|
|
||||||
bool writing;
|
bool writing;
|
||||||
bool shouldClose;
|
|
||||||
bool eos;
|
bool eos;
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
ProcessStream(HANDLE strm, bool writing)
|
||||||
#else
|
{
|
||||||
ProcessStream(int strm, bool writing, bool shouldClose)
|
this->strm = strm;
|
||||||
|
this->writing = writing;
|
||||||
|
this->eos = false;
|
||||||
|
}
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
|
#else
|
||||||
|
ProcessStream(int strm, bool writing)
|
||||||
{
|
{
|
||||||
this->strm = strm;
|
this->strm = strm;
|
||||||
this->writing = writing;
|
this->writing = writing;
|
||||||
this->shouldClose=shouldClose;
|
|
||||||
this->eos=false;
|
this->eos=false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -59,8 +133,8 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return true;
|
return this->strm == NULL || eos;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
return this->strm < 0 || eos;
|
return this->strm < 0 || eos;
|
||||||
@ -70,8 +144,8 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return false;
|
return !writing && this->strm != NULL;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
return !writing && this->strm > -1;
|
return !writing && this->strm > -1;
|
||||||
@ -81,8 +155,9 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return false;
|
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
return writing && this->strm != NULL;
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
return writing && this->strm > -1;
|
return writing && this->strm > -1;
|
||||||
@ -93,8 +168,16 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
if (this->strm == NULL || this->eos && writing) return 0;
|
||||||
|
|
||||||
|
DWORD dataR = (DWORD)sz;
|
||||||
|
if (!ReadFile(this->strm, buff, dataR, &dataR, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
if (dataR == 0) {
|
||||||
|
this->eos = true;
|
||||||
|
}
|
||||||
|
return (size_t)dataR;
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
if(this->strm < 0 || this->eos && writing) return 0;
|
if(this->strm < 0 || this->eos && writing) return 0;
|
||||||
@ -110,30 +193,22 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
//TODO: Implement for WIN32
|
//TODO: Implement for WIN32
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
if (this->strm == NULL || !writing) return 0;
|
||||||
|
DWORD dataW=(DWORD)sz;
|
||||||
|
if (!WriteFile(this->strm, buff, dataW, &dataW, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
|
||||||
|
return (size_t)dataW;
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
if(this->strm < 0 && !writing) return 0;
|
if(this->strm < 0 || !writing) return 0;
|
||||||
auto r = write(this->strm,buff,sz);
|
auto r = write(this->strm,buff,sz);
|
||||||
if(r == -1) return 0;
|
if(r == -1) return 0;
|
||||||
return (size_t)r;
|
return (size_t)r;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
~ProcessStream()
|
|
||||||
{
|
|
||||||
//TODO: Implement for WIN32
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
|
||||||
//do nothing
|
|
||||||
#else
|
|
||||||
if(this->strm > -1 && this->shouldClose)
|
|
||||||
close(this->strm);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -153,6 +228,31 @@ namespace Tesses::Framework::Platform {
|
|||||||
this->includeThisEnv = includeThisEnv;
|
this->includeThisEnv = includeThisEnv;
|
||||||
this->hidden.AllocField<ProcessData>();
|
this->hidden.AllocField<ProcessData>();
|
||||||
}
|
}
|
||||||
|
bool Process::HasExited()
|
||||||
|
{
|
||||||
|
if (this->exited) return true;
|
||||||
|
ProcessData* p = this->hidden.GetField<ProcessData*>();
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (WaitForSingleObject(p->pi.hProcess, 0) == WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
DWORD ec = 0;
|
||||||
|
GetExitCodeProcess(p->pi.hProcess,&ec);
|
||||||
|
this->exitCode = (int)ec;
|
||||||
|
this->exited = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
int r;
|
||||||
|
if (waitpid(this->hidden.GetField<ProcessData*>()->pid, &r, WNOHANG) != -1)
|
||||||
|
{
|
||||||
|
this->exited = true;
|
||||||
|
this->exitCode = r;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Process::Process(std::string name, std::vector<std::string> args, std::vector<std::string> env,bool includeThisEnv) : Process(name,args,std::vector<std::pair<std::string,std::string>>(),includeThisEnv)
|
Process::Process(std::string name, std::vector<std::string> args, std::vector<std::string> env,bool includeThisEnv) : Process(name,args,std::vector<std::pair<std::string,std::string>>(),includeThisEnv)
|
||||||
{
|
{
|
||||||
this->env.resize(env.size());
|
this->env.resize(env.size());
|
||||||
@ -172,16 +272,70 @@ namespace Tesses::Framework::Platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Process::CloseStdInNow()
|
||||||
|
{
|
||||||
|
ProcessData* p = this->hidden.GetField<ProcessData*>();
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (p->stdin_strm != NULL)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
p->stdin_strm = NULL;
|
||||||
|
}
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (p->stdin_strm > -1)
|
||||||
|
{
|
||||||
|
close(p->stdin_strm);
|
||||||
|
p->stdin_strm = -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
Process::~Process()
|
Process::~Process()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
ProcessData* p = this->hidden.GetField<ProcessData*>();
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if(!this->exited)
|
||||||
|
Kill(SIGTERM);
|
||||||
|
if (p->stdin_strm != NULL)
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
|
||||||
|
if (p->stdout_strm != NULL)
|
||||||
|
CloseHandle(p->stdout_strm);
|
||||||
|
|
||||||
|
if (p->stderr_strm != NULL)
|
||||||
|
CloseHandle(p->stderr_strm);
|
||||||
|
|
||||||
|
|
||||||
|
CloseHandle(p->pi.hProcess);
|
||||||
|
CloseHandle(p->pi.hThread);
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (!this->exited)
|
||||||
|
{
|
||||||
|
Kill(SIGTERM);
|
||||||
|
WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->stdin_strm != -1)
|
||||||
|
close(p->stdin_strm);
|
||||||
|
if (p->stdout_strm != -1)
|
||||||
|
close(p->stdout_strm);
|
||||||
|
if (p->stderr_strm != -1)
|
||||||
|
close(p->stderr_strm);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Process::Start()
|
bool Process::Start()
|
||||||
{
|
{
|
||||||
auto p =
|
ProcessData* p =
|
||||||
this->hidden.GetField<ProcessData*>();
|
this->hidden.GetField<ProcessData*>();
|
||||||
std::vector<std::pair<std::string,std::string>> envs;
|
std::vector<std::pair<std::string,std::string>> envs;
|
||||||
|
|
||||||
@ -195,6 +349,7 @@ namespace Tesses::Framework::Platform {
|
|||||||
{
|
{
|
||||||
if(item.first == itemNew.first)
|
if(item.first == itemNew.first)
|
||||||
{
|
{
|
||||||
|
|
||||||
item.second = itemNew.second;
|
item.second = itemNew.second;
|
||||||
has=true;
|
has=true;
|
||||||
break;
|
break;
|
||||||
@ -204,8 +359,144 @@ namespace Tesses::Framework::Platform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
|
||||||
|
ZeroMemory(&p->si, sizeof(p->si));
|
||||||
|
p->si.cb = sizeof(p->si);
|
||||||
|
ZeroMemory(&p->pi, sizeof(p->pi));
|
||||||
|
std::u16string u16_name;
|
||||||
|
std::u16string u16_args;
|
||||||
|
std::string args;
|
||||||
|
escape_windows_args(args,this->args);
|
||||||
|
UTF16::FromUTF8(u16_name,this->name);
|
||||||
|
UTF16::FromUTF8(u16_args, args);
|
||||||
|
std::u16string env = {};
|
||||||
|
|
||||||
|
for (auto envItem : envs)
|
||||||
|
{
|
||||||
|
auto partOld = envItem.first + "=" + envItem.second;
|
||||||
|
std::u16string part = {};
|
||||||
|
|
||||||
|
UTF16::FromUTF8(part,partOld);
|
||||||
|
env.append(part);
|
||||||
|
env.push_back(0);
|
||||||
|
}
|
||||||
|
env.push_back(0);
|
||||||
|
|
||||||
|
std::u16string workDir = {};
|
||||||
|
|
||||||
|
if (!this->workingDirectory.empty())
|
||||||
|
UTF16::FromUTF8(workDir, this->workingDirectory);
|
||||||
|
|
||||||
|
SECURITY_ATTRIBUTES attr;
|
||||||
|
attr.nLength = sizeof(attr);
|
||||||
|
attr.lpSecurityDescriptor = NULL;
|
||||||
|
attr.bInheritHandle = true;
|
||||||
|
p->si.hStdInput = NULL;
|
||||||
|
p->si.hStdOutput = NULL;
|
||||||
|
|
||||||
|
p->si.hStdError = NULL;
|
||||||
|
|
||||||
|
p->stdin_strm = NULL;
|
||||||
|
p->stdout_strm = NULL;
|
||||||
|
p->stderr_strm = NULL;
|
||||||
|
if (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr)
|
||||||
|
{
|
||||||
|
p->si.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
if (!this->redirectStdIn)
|
||||||
|
{
|
||||||
|
p->si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
}
|
||||||
|
if (!this->redirectStdOut)
|
||||||
|
{
|
||||||
|
|
||||||
|
p->si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
}
|
||||||
|
if (!this->redirectStdOut)
|
||||||
|
{
|
||||||
|
p->si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
if (!CreatePipe(&p->si.hStdInput, &p->stdin_strm, &attr,0)) return false;
|
||||||
|
|
||||||
|
SetHandleInformation(p->stdin_strm, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->redirectStdOut)
|
||||||
|
{
|
||||||
|
if (!CreatePipe(&p->stdout_strm, &p->si.hStdOutput, &attr, 0))
|
||||||
|
{
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
CloseHandle(p->si.hStdInput);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
}
|
||||||
|
|
||||||
|
SetHandleInformation(p->stdout_strm, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
}
|
||||||
|
if (this->redirectStdErr)
|
||||||
|
{
|
||||||
|
if (!CreatePipe(&p->stderr_strm, &p->si.hStdError, &attr, 0))
|
||||||
|
{
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
CloseHandle(p->si.hStdInput);
|
||||||
|
}
|
||||||
|
if (this->redirectStdOut)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdout_strm);
|
||||||
|
CloseHandle(p->si.hStdOutput);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHandleInformation(p->stderr_strm, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CreateProcessW((LPCWSTR)u16_name.c_str(), (LPWSTR)u16_args.data(), NULL, NULL, (this->redirectStdIn || this->redirectStdOut || this->redirectStdErr), CREATE_UNICODE_ENVIRONMENT, (LPVOID)env.c_str(), workDir.empty() ? (LPCWSTR)NULL : (LPCWSTR)workDir.c_str(), &(p->si), &(p->pi)))
|
||||||
|
{
|
||||||
|
if (this->redirectStdIn)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdin_strm);
|
||||||
|
CloseHandle(p->si.hStdInput);
|
||||||
|
}
|
||||||
|
if (this->redirectStdOut)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stdout_strm);
|
||||||
|
CloseHandle(p->si.hStdOutput);
|
||||||
|
}
|
||||||
|
if (this->redirectStdErr)
|
||||||
|
{
|
||||||
|
CloseHandle(p->stderr_strm);
|
||||||
|
CloseHandle(p->si.hStdError);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
BOOL
|
||||||
|
WINAPI
|
||||||
|
CreateProcessW(
|
||||||
|
_In_opt_ LPCWSTR lpApplicationName,
|
||||||
|
_Inout_opt_ LPWSTR lpCommandLine,
|
||||||
|
_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
|
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
|
_In_ BOOL bInheritHandles,
|
||||||
|
_In_ DWORD dwCreationFlags,
|
||||||
|
_In_opt_ LPVOID lpEnvironment,
|
||||||
|
_In_opt_ LPCWSTR lpCurrentDirectory,
|
||||||
|
_In_ LPSTARTUPINFOW lpStartupInfo,
|
||||||
|
_Out_ LPPROCESS_INFORMATION lpProcessInformation
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -278,6 +569,7 @@ namespace Tesses::Framework::Platform {
|
|||||||
std::vector<std::string> env2;
|
std::vector<std::string> env2;
|
||||||
env2.resize(envs.size());
|
env2.resize(envs.size());
|
||||||
|
|
||||||
|
|
||||||
for(size_t i = 0; i < envs.size(); i++)
|
for(size_t i = 0; i < envs.size(); i++)
|
||||||
{
|
{
|
||||||
env2[i] = envs[i].first + "=" + envs[i].second;
|
env2[i] = envs[i].first + "=" + envs[i].second;
|
||||||
@ -286,13 +578,13 @@ namespace Tesses::Framework::Platform {
|
|||||||
char** argv = new char*[args.size()+1];
|
char** argv = new char*[args.size()+1];
|
||||||
argv[args.size()]=NULL;
|
argv[args.size()]=NULL;
|
||||||
char** envp = new char*[env2.size()+1];
|
char** envp = new char*[env2.size()+1];
|
||||||
envp[env.size()]=NULL;
|
envp[env2.size()]=NULL;
|
||||||
|
|
||||||
for(size_t i = 0; i < args.size();i++)
|
for(size_t i = 0; i < args.size();i++)
|
||||||
{
|
{
|
||||||
argv[i] = (char*)args[i].c_str();
|
argv[i] = (char*)args[i].c_str();
|
||||||
}
|
}
|
||||||
for(size_t i = 0; i < env.size();i++)
|
for(size_t i = 0; i < env2.size();i++)
|
||||||
{
|
{
|
||||||
envp[i] = (char*)env2[i].c_str();
|
envp[i] = (char*)env2[i].c_str();
|
||||||
}
|
}
|
||||||
@ -330,10 +622,31 @@ namespace Tesses::Framework::Platform {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Process::Kill(int signal)
|
void Process::Kill(int signal)
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
if (signal != SIGKILL && signal != SIGTERM) std::cout << "WARN: We terminated the process" << std::endl;
|
||||||
|
|
||||||
|
if (signal == SIGTERM)
|
||||||
|
{
|
||||||
|
auto win = this->hidden.GetField<ProcessData*>();
|
||||||
|
if (EnumWindows(ProcessData::KillGraceFully, (LPARAM)(void*)win))
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(win->pi.hProcess, 60000) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
PostThreadMessage(win->pi.dwThreadId, WM_QUIT, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PostThreadMessage(win->pi.dwThreadId, WM_QUIT, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TerminateProcess(this->hidden.GetField<ProcessData*>()->pi.hProcess,-1);
|
||||||
|
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
#else
|
#else
|
||||||
kill(this->hidden.GetField<ProcessData*>()->pid,signal);
|
kill(this->hidden.GetField<ProcessData*>()->pid,signal);
|
||||||
#endif
|
#endif
|
||||||
@ -341,45 +654,57 @@ namespace Tesses::Framework::Platform {
|
|||||||
|
|
||||||
int Process::WaitForExit()
|
int Process::WaitForExit()
|
||||||
{
|
{
|
||||||
|
if (this->exited) return this->exitCode;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
auto p = this->hidden.GetField<ProcessData*>();
|
||||||
reutnr -1;
|
WaitForSingleObject(p->pi.hProcess, INFINITE);
|
||||||
|
DWORD ret=0;
|
||||||
|
GetExitCodeProcess(p->pi.hThread, &ret);
|
||||||
|
this->exitCode = (int)ret;
|
||||||
|
this->exited = true;
|
||||||
|
return (int)ret;
|
||||||
|
|
||||||
|
#elif defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
|
return -1;
|
||||||
#else
|
#else
|
||||||
int r;
|
int r;
|
||||||
if(waitpid(this->hidden.GetField<ProcessData*>()->pid,&r,0) != -1)
|
if (waitpid(this->hidden.GetField<ProcessData*>()->pid, &r, 0) != -1)
|
||||||
|
{
|
||||||
|
this->exited = true;
|
||||||
|
this->exitCode = r;
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Tesses::Framework::Streams::Stream* Process::GetStdinStream(bool closeUnderlying)
|
Tesses::Framework::Streams::Stream* Process::GetStdinStream()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
if (this->exited) return nullptr;
|
||||||
return nullptr;
|
#if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true,closeUnderlying);
|
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdin_strm,true);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Tesses::Framework::Streams::Stream* Process::GetStdoutStream(bool closeUnderlying)
|
Tesses::Framework::Streams::Stream* Process::GetStdoutStream()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
|
||||||
return nullptr;
|
if (this->exited) return nullptr;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false,closeUnderlying);
|
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stdout_strm,false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Tesses::Framework::Streams::Stream* Process::GetStderrStream(bool closeUnderlying)
|
Tesses::Framework::Streams::Stream* Process::GetStderrStream()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
|
||||||
return nullptr;
|
if (this->exited) return nullptr;
|
||||||
#elif defined(GEKKO) || defined(__PS2__) defined(__SWITCH__)
|
#if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#else
|
#else
|
||||||
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false,closeUnderlying);
|
return new ProcessStream(this->hidden.GetField<ProcessData*>()->stderr_strm,false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,12 @@ extern "C" {
|
|||||||
namespace Tesses::Framework::SDL2
|
namespace Tesses::Framework::SDL2
|
||||||
{
|
{
|
||||||
GUI gui;
|
GUI gui;
|
||||||
|
void GUI::CloseWindows()
|
||||||
|
{
|
||||||
|
auto wins=this->windows;
|
||||||
|
for(auto win : wins) delete win;
|
||||||
|
this->windows.clear();
|
||||||
|
}
|
||||||
void GUI::Update()
|
void GUI::Update()
|
||||||
{
|
{
|
||||||
if(this->windows.empty()) return;
|
if(this->windows.empty()) return;
|
||||||
@ -28,7 +34,8 @@ namespace Tesses::Framework::SDL2
|
|||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while(SDL_PollEvent(&event))
|
while(SDL_PollEvent(&event))
|
||||||
{
|
{
|
||||||
for(auto win : this->windows)
|
auto windows = this->windows;
|
||||||
|
for(auto& win : windows)
|
||||||
{
|
{
|
||||||
if(win == nullptr) continue;
|
if(win == nullptr) continue;
|
||||||
auto id = SDL_GetWindowID(win->window);
|
auto id = SDL_GetWindowID(win->window);
|
||||||
@ -37,6 +44,18 @@ namespace Tesses::Framework::SDL2
|
|||||||
case SDL_EventType::SDL_WINDOWEVENT:
|
case SDL_EventType::SDL_WINDOWEVENT:
|
||||||
if(event.window.windowID == id)
|
if(event.window.windowID == id)
|
||||||
{
|
{
|
||||||
|
if(event.window.event == SDL_WINDOWEVENT_CLOSE)
|
||||||
|
{
|
||||||
|
GUIWindowClosingEventArgs e;
|
||||||
|
e.cancel=false;
|
||||||
|
win->Closing.Invoke(win,e);
|
||||||
|
if(!e.cancel)
|
||||||
|
{
|
||||||
|
delete win;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
win->Event(event);
|
win->Event(event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -168,28 +187,31 @@ namespace Tesses::Framework::SDL2
|
|||||||
GUIPalette::GUIPalette()
|
GUIPalette::GUIPalette()
|
||||||
{
|
{
|
||||||
this->fontSize=24;
|
this->fontSize=24;
|
||||||
|
this->borderSize = 2;
|
||||||
}
|
}
|
||||||
SDL_Color& GUIPalette::GetBorderColor(bool isHovering, bool isActive, bool isMouseDown)
|
SDL_Color& GUIPalette::GetBorderColor(bool isHovering, bool isActive, bool isMouseDown)
|
||||||
{
|
{
|
||||||
bool isHovering2=isHovering ^ isMouseDown;
|
bool isHovering2=isHovering ^ isMouseDown;
|
||||||
if(isHovering2 && isActive)
|
if(isHovering2 && isActive)
|
||||||
return this->border_hover_active;
|
return this->borderHoverActive;
|
||||||
if(isHovering2)
|
if(isHovering2)
|
||||||
return this->border_hover;
|
return this->borderHover;
|
||||||
if(isActive)
|
if(isActive)
|
||||||
return this->border_active;
|
return this->borderActive;
|
||||||
return this->border_color;
|
return this->borderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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,int borderSize)
|
||||||
{
|
{
|
||||||
|
|
||||||
this->accent=accent;
|
this->accent=accent;
|
||||||
this->background = background;
|
this->background = background;
|
||||||
this->border_color=border_color;
|
this->borderColor=border_color;
|
||||||
this->border_hover = border_hover;
|
this->borderHover = border_hover;
|
||||||
this->border_active = border_active;
|
this->borderActive = border_active;
|
||||||
this->border_hover_active=border_hover_active;
|
this->borderHoverActive=border_hover_active;
|
||||||
this->fontSize = fontSize;
|
this->fontSize = fontSize;
|
||||||
|
this->borderSize = borderSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GUIEventArgs::Type()
|
std::string GUIEventArgs::Type()
|
||||||
@ -212,33 +234,38 @@ namespace Tesses::Framework::SDL2
|
|||||||
{
|
{
|
||||||
return "SDLEvent";
|
return "SDLEvent";
|
||||||
}
|
}
|
||||||
|
std::string GUIWindowClosingEventArgs::Type()
|
||||||
|
{
|
||||||
|
return "WindowClosing";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
GUIPalette::GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize)
|
GUIPalette::GUIPalette(bool isDarkMode, SDL_Color accent,int fontSize,int borderSize)
|
||||||
{
|
{
|
||||||
this->accent = accent;
|
this->accent = accent;
|
||||||
this->fontSize = fontSize;
|
this->fontSize = fontSize;
|
||||||
|
this->borderSize = borderSize;
|
||||||
|
|
||||||
if(isDarkMode)
|
if(isDarkMode)
|
||||||
{
|
{
|
||||||
this->background = {.r = 42,.g=42,.b=42,.a=255};
|
this->background = {.r = 42,.g=42,.b=42,.a=255};
|
||||||
this->border_color = {.r=0,.g=0,.b=0,.a=255};
|
this->borderColor = {.r=0,.g=0,.b=0,.a=255};
|
||||||
this->border_hover = {.r=92,.g=92,.b=92,.a=255};
|
this->borderHover = {.r=92,.g=92,.b=92,.a=255};
|
||||||
|
|
||||||
this->border_active = {.r=200,.g=200,.b=200,.a=255};
|
this->borderActive = {.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};
|
this->borderHoverActive = {.r=(uint8_t)(255-accent.r),.g=(uint8_t)(255-accent.g),.b=(uint8_t)(255-accent.b),.a=255};
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->background = {.r=239,.g=239,.b=239,.a=255};
|
this->background = {.r=239,.g=239,.b=239,.a=255};
|
||||||
this->border_color = {.r=0,.g=0,.b=0,.a=255};
|
this->borderColor = {.r=0,.g=0,.b=0,.a=255};
|
||||||
|
|
||||||
this->border_active = {.r=92,.g=92,.b=92,.a=255};
|
this->borderActive = {.r=92,.g=92,.b=92,.a=255};
|
||||||
|
|
||||||
this->border_hover = {.r=200,.g=200,.b=200,.a=255};
|
this->borderHover = {.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};
|
this->borderHoverActive = {.r=(uint8_t)(255-accent.r),.g=(uint8_t)(255-accent.g),.b=(uint8_t)(255-accent.b),.a=255};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
105
src/SDL2/GUIPopup.cpp
Normal file
105
src/SDL2/GUIPopup.cpp
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "TessesFramework/SDL2/GUI.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2 {
|
||||||
|
size_t GUIPopup::ViewCount()
|
||||||
|
{
|
||||||
|
return this->GetView() != nullptr ? 1 : 0;
|
||||||
|
}
|
||||||
|
View* GUIPopup::GetViewAt(size_t index)
|
||||||
|
{
|
||||||
|
if(index > 0) return nullptr;
|
||||||
|
return this->GetView();
|
||||||
|
}
|
||||||
|
GUIPopup::GUIPopup() : GUIPopup(0,0,0,0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
GUIPopup::GUIPopup(SDL_Rect bounds)
|
||||||
|
{
|
||||||
|
this->bounds = bounds;
|
||||||
|
}
|
||||||
|
GUIPopup::GUIPopup(int x, int y,int w, int h)
|
||||||
|
{
|
||||||
|
this->bounds.x = x;
|
||||||
|
this->bounds.y = y;
|
||||||
|
this->bounds.w = w;
|
||||||
|
this->bounds.h = h;
|
||||||
|
}
|
||||||
|
View* GUIContainerPopup::GetView()
|
||||||
|
{
|
||||||
|
return this->child;
|
||||||
|
}
|
||||||
|
GUIContainerPopup::GUIContainerPopup() : GUIPopup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
GUIContainerPopup::GUIContainerPopup(SDL_Rect bounds) : GUIPopup(bounds)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
GUIContainerPopup::GUIContainerPopup(int x, int y,int w, int h) : GUIPopup(x,y,w,h)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GUIContainerPopup::SetView(View* view, bool owns)
|
||||||
|
{
|
||||||
|
if(this->ownsChild && this->child != view)
|
||||||
|
delete this->child;
|
||||||
|
this->child = view;
|
||||||
|
this->ownsChild=owns;
|
||||||
|
this->AssignChildParentToThis(view);
|
||||||
|
}
|
||||||
|
GUIContainerPopup::~GUIContainerPopup()
|
||||||
|
{
|
||||||
|
if(this->ownsChild)
|
||||||
|
delete this->child;
|
||||||
|
}
|
||||||
|
GUIPopup::~GUIPopup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUIPopup::Close()
|
||||||
|
{
|
||||||
|
|
||||||
|
this->closed=true;
|
||||||
|
}
|
||||||
|
bool GUIPopup::IsClosed()
|
||||||
|
{
|
||||||
|
return this->closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUIPopup::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
SDL_SetRenderDrawColor(renderer,win->palette.background.r,win->palette.background.g,win->palette.background.b,win->palette.background.a);
|
||||||
|
SDL_RenderFillRect(renderer,&r);
|
||||||
|
auto view = GetView();
|
||||||
|
if(view != nullptr)
|
||||||
|
CallOnDraw(view,renderer,r);
|
||||||
|
}
|
||||||
|
bool GUIPopup::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
||||||
|
{
|
||||||
|
auto view = GetView();
|
||||||
|
if(view != nullptr)
|
||||||
|
{
|
||||||
|
if(CallOnEvent(view,event,myBounds,myVisibleBounds)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return View::OnEvent(event,myBounds,myVisibleBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GUIPopup::IsActive()
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
if(win == nullptr) return false;
|
||||||
|
if(win->popups.empty()) return false;
|
||||||
|
|
||||||
|
return win->popups.back() == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -9,6 +9,12 @@
|
|||||||
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
|
#include "TessesFramework/SDL2/Views/AbsoluteView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
|
#include "TessesFramework/SDL2/Views/EditTextView.hpp"
|
||||||
#include "TessesFramework/SDL2/Views/PictureView.hpp"
|
#include "TessesFramework/SDL2/Views/PictureView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/ScrollableTextListView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/HScrollView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/VScrollView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/HStackView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/VStackView.hpp"
|
||||||
|
#include "TessesFramework/SDL2/Views/DropDownView.hpp"
|
||||||
#include "TessesFramework/SDL2/ParseColor.hpp"
|
#include "TessesFramework/SDL2/ParseColor.hpp"
|
||||||
|
|
||||||
#if defined(__SWITCH__)
|
#if defined(__SWITCH__)
|
||||||
@ -19,11 +25,23 @@ extern "C" {
|
|||||||
|
|
||||||
namespace Tesses::Framework::SDL2
|
namespace Tesses::Framework::SDL2
|
||||||
{
|
{
|
||||||
|
GUIWindow::operator bool()
|
||||||
|
{
|
||||||
|
if(this == nullptr) return false;
|
||||||
|
for(auto item : gui.windows)
|
||||||
|
if(item == this) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
void GUIWindow::MakeActive(View* view)
|
void GUIWindow::MakeActive(View* view)
|
||||||
{
|
{
|
||||||
if(!view->GetViewFlag(VIEWFLAG_TABSTOP)) return;
|
if(!view->GetViewFlag(VIEWFLAG_TABSTOP)) return;
|
||||||
if(view->GetViewFlag(VIEWFLAG_ISACTIVE)) return;
|
if(view->GetViewFlag(VIEWFLAG_ISACTIVE)) return;
|
||||||
|
if(this->popups.empty())
|
||||||
DeactivateAll(this);
|
DeactivateAll(this);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeactivateAll(this->popups.back());
|
||||||
|
}
|
||||||
view->SetViewFlag(VIEWFLAG_ISACTIVE,true);
|
view->SetViewFlag(VIEWFLAG_ISACTIVE,true);
|
||||||
}
|
}
|
||||||
void GUIWindow::DeactivateAll(View* view)
|
void GUIWindow::DeactivateAll(View* view)
|
||||||
@ -123,6 +141,7 @@ namespace Tesses::Framework::SDL2
|
|||||||
}
|
}
|
||||||
void GUIWindow::Event(SDL_Event& event)
|
void GUIWindow::Event(SDL_Event& event)
|
||||||
{
|
{
|
||||||
|
|
||||||
int w,h;
|
int w,h;
|
||||||
SDL_GetWindowSize(window,&w,&h);
|
SDL_GetWindowSize(window,&w,&h);
|
||||||
SDL_Rect r={.x=0,.y=0,.w=w,.h=h};
|
SDL_Rect r={.x=0,.y=0,.w=w,.h=h};
|
||||||
@ -135,6 +154,8 @@ namespace Tesses::Framework::SDL2
|
|||||||
SDL_RenderClear(renderer);
|
SDL_RenderClear(renderer);
|
||||||
if(this->child != nullptr)
|
if(this->child != nullptr)
|
||||||
this->child->OnDraw(renderer,r);
|
this->child->OnDraw(renderer,r);
|
||||||
|
for(auto popup : this->popups)
|
||||||
|
popup->OnDraw(renderer,popup->bounds);
|
||||||
SDL_RenderPresent(renderer);
|
SDL_RenderPresent(renderer);
|
||||||
}
|
}
|
||||||
bool GUIWindow::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
bool GUIWindow::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
||||||
@ -145,11 +166,75 @@ namespace Tesses::Framework::SDL2
|
|||||||
GUISDLEventEventArgs sdle;
|
GUISDLEventEventArgs sdle;
|
||||||
sdle.event = event;
|
sdle.event = event;
|
||||||
this->SDLEvent.Invoke(this,sdle);
|
this->SDLEvent.Invoke(this,sdle);
|
||||||
|
if(this->popups.empty())
|
||||||
TabNext();
|
TabNext();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TabNextResult nr=TabNextResult::KeepGoing;
|
||||||
|
TabNext(this->popups.back(),nr);
|
||||||
|
if(nr != TabNextResult::Done)
|
||||||
|
{
|
||||||
|
nr = TabNextResult::TabNext;
|
||||||
|
TabNext(this->popups.back(),nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(this->child != nullptr) { GUISDLEventEventArgs sdle;
|
if(this->child != nullptr) {
|
||||||
sdle.event = event; this->SDLEvent.Invoke(this,sdle); return this->child->OnEvent(event,myBounds,myVisibleBounds);}
|
GUISDLEventEventArgs sdle;
|
||||||
|
sdle.event = event; this->SDLEvent.Invoke(this,sdle);
|
||||||
|
retry:
|
||||||
|
if(this->popups.empty())
|
||||||
|
return this->child->OnEvent(event,myBounds,myVisibleBounds);
|
||||||
|
else {
|
||||||
|
if(event.type == SDL_MOUSEBUTTONDOWN)
|
||||||
|
{
|
||||||
|
auto popup = this->popups.back();
|
||||||
|
if(event.button.x >= popup->bounds.x && event.button.x < popup->bounds.x+popup->bounds.w && event.button.y >= popup->bounds.y && event.button.y < popup->bounds.y+popup->bounds.h)
|
||||||
|
{
|
||||||
|
return popup->OnEvent(event,popup->bounds,popup->bounds);
|
||||||
|
}
|
||||||
|
else if(popup->closeIfClickOutside) {
|
||||||
|
popup->closed=true;
|
||||||
|
this->popups.pop_back();
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto popup = this->popups.back();
|
||||||
|
return popup->OnEvent(event,popup->bounds,popup->bounds);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retry2:
|
||||||
|
if(!this->popups.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
if(event.type == SDL_MOUSEBUTTONDOWN)
|
||||||
|
{
|
||||||
|
auto popup = this->popups.back();
|
||||||
|
if(event.button.x >= popup->bounds.x && event.button.x < popup->bounds.x+popup->bounds.w && event.button.y >= popup->bounds.y && event.button.y < popup->bounds.y+popup->bounds.h)
|
||||||
|
{
|
||||||
|
return popup->OnEvent(event,popup->bounds,popup->bounds);
|
||||||
|
}
|
||||||
|
else if(popup->closeIfClickOutside)
|
||||||
|
{
|
||||||
|
popup->closed=true;
|
||||||
|
this->popups.pop_back();
|
||||||
|
goto retry2;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto popup = this->popups.back();
|
||||||
|
return popup->OnEvent(event,popup->bounds,popup->bounds);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return View::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)
|
GUIWindow::GUIWindow(std::string title, int w, int h, Uint32 flags, const GUIPalette& palette) : ContainerView(title)
|
||||||
@ -245,6 +330,36 @@ namespace Tesses::Framework::SDL2
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUIWindow::ShowPopup(GUIPopup* popup)
|
||||||
|
{
|
||||||
|
popup->closed=false;
|
||||||
|
bool has = false;
|
||||||
|
for(auto item : this->popups)
|
||||||
|
if(item == popup) { has=true; break;}
|
||||||
|
if(!has)
|
||||||
|
this->popups.push_back(popup);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AssignChildParentToThis(popup);
|
||||||
|
|
||||||
|
auto v = popup->GetView();
|
||||||
|
if(v != nullptr) this->MakeActive(v);
|
||||||
|
|
||||||
|
while(!popup->IsClosed() && TF_IsRunning())
|
||||||
|
{
|
||||||
|
TF_RunEventLoopItteration();
|
||||||
|
}
|
||||||
|
if(!this->popups.empty() && this->popups.back() == popup)
|
||||||
|
this->popups.pop_back();
|
||||||
|
popup->closed=true;
|
||||||
|
}
|
||||||
|
void GUIWindow::ShowPopup(GUIPopup& popup)
|
||||||
|
{
|
||||||
|
ShowPopup(&popup);
|
||||||
|
}
|
||||||
|
|
||||||
void GUIWindow::SetView(Tesses::Framework::Serialization::Json::JToken item)
|
void GUIWindow::SetView(Tesses::Framework::Serialization::Json::JToken item)
|
||||||
{
|
{
|
||||||
Tesses::Framework::Serialization::Json::JObject dict;
|
Tesses::Framework::Serialization::Json::JObject dict;
|
||||||
@ -288,13 +403,13 @@ namespace Tesses::Framework::SDL2
|
|||||||
if(pal0.TryGetValueAsType("Background",_str))
|
if(pal0.TryGetValueAsType("Background",_str))
|
||||||
TryParseSDLColor(_str,pal.background);
|
TryParseSDLColor(_str,pal.background);
|
||||||
if(pal0.TryGetValueAsType("Border",_str))
|
if(pal0.TryGetValueAsType("Border",_str))
|
||||||
TryParseSDLColor(_str,pal.border_color);
|
TryParseSDLColor(_str,pal.borderColor);
|
||||||
if(pal0.TryGetValueAsType("BorderActive",_str))
|
if(pal0.TryGetValueAsType("BorderActive",_str))
|
||||||
TryParseSDLColor(_str,pal.border_active);
|
TryParseSDLColor(_str,pal.borderActive);
|
||||||
if(pal0.TryGetValueAsType("BorderHover",_str))
|
if(pal0.TryGetValueAsType("BorderHover",_str))
|
||||||
TryParseSDLColor(_str,pal.border_hover);
|
TryParseSDLColor(_str,pal.borderHover);
|
||||||
if(pal0.TryGetValueAsType("BorderHoverActive",_str))
|
if(pal0.TryGetValueAsType("BorderHoverActive",_str))
|
||||||
TryParseSDLColor(_str,pal.border_hover_active);
|
TryParseSDLColor(_str,pal.borderHoverActive);
|
||||||
this->SetPalette(pal);
|
this->SetPalette(pal);
|
||||||
}
|
}
|
||||||
if(dict.TryGetValueAsType("Title",title) || dict.TryGetValueAsType("Text",title))
|
if(dict.TryGetValueAsType("Title",title) || dict.TryGetValueAsType("Text",title))
|
||||||
@ -312,7 +427,18 @@ namespace Tesses::Framework::SDL2
|
|||||||
return this->renderer;
|
return this->renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int szStr2size(std::string sz)
|
||||||
|
{
|
||||||
|
if(sz.empty()) return GUI_MIN;
|
||||||
|
if(sz == "min") return GUI_MIN;
|
||||||
|
if(sz == "*") return GUI_EXPAND;
|
||||||
|
if(sz[0] == '*') {
|
||||||
|
return GUI_EXPAND_N(std::stoi(sz.substr(1)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return std::stoi(sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
View* GUIWindow::CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json)
|
View* GUIWindow::CreateViewFromJson(Tesses::Framework::Serialization::Json::JObject json)
|
||||||
{
|
{
|
||||||
@ -382,6 +508,33 @@ namespace Tesses::Framework::SDL2
|
|||||||
tlv->selected = (int)index;
|
tlv->selected = (int)index;
|
||||||
return tlv;
|
return tlv;
|
||||||
}
|
}
|
||||||
|
else if(type == "ScrollableTextListView")
|
||||||
|
{
|
||||||
|
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::ScrollableTextListView();
|
||||||
|
|
||||||
|
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")
|
else if(type == "AbsoluteView")
|
||||||
{
|
{
|
||||||
auto av = new Views::AbsoluteView();
|
auto av = new Views::AbsoluteView();
|
||||||
@ -432,6 +585,119 @@ namespace Tesses::Framework::SDL2
|
|||||||
pv->SetId(id);
|
pv->SetId(id);
|
||||||
return pv;
|
return pv;
|
||||||
}
|
}
|
||||||
|
else if(type == "DropDownView")
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
auto tlv = new Views::DropDownView();
|
||||||
|
|
||||||
|
tlv->SetViewFlag(VIEWFLAG_ISACTIVE,active);
|
||||||
|
tlv->SetId(id);
|
||||||
|
tlv->GetItems() = items;
|
||||||
|
|
||||||
|
tlv->SetIndex((int)index);
|
||||||
|
return tlv;
|
||||||
|
}
|
||||||
|
else if(type == "VScrollView")
|
||||||
|
{
|
||||||
|
int64_t value=0;
|
||||||
|
int64_t min = 0;
|
||||||
|
int64_t max = 10;
|
||||||
|
json.TryGetValueAsType("Value",value);
|
||||||
|
|
||||||
|
json.TryGetValueAsType("Min",min);
|
||||||
|
|
||||||
|
json.TryGetValueAsType("Max",max);
|
||||||
|
auto vscroll=new Views::VScrollView();
|
||||||
|
vscroll->value = (uint64_t)value;
|
||||||
|
vscroll->min = (uint64_t)min;
|
||||||
|
vscroll->max = (uint64_t)max;
|
||||||
|
vscroll->SetId(id);
|
||||||
|
return vscroll;
|
||||||
|
}
|
||||||
|
else if(type == "HScrollView")
|
||||||
|
{
|
||||||
|
int64_t value=0;
|
||||||
|
int64_t min = 0;
|
||||||
|
int64_t max = 10;
|
||||||
|
json.TryGetValueAsType("Value",value);
|
||||||
|
|
||||||
|
json.TryGetValueAsType("Min",min);
|
||||||
|
|
||||||
|
json.TryGetValueAsType("Max",max);
|
||||||
|
auto hscroll=new Views::VScrollView();
|
||||||
|
hscroll->value = (uint64_t)value;
|
||||||
|
hscroll->min = (uint64_t)min;
|
||||||
|
hscroll->max = (uint64_t)max;
|
||||||
|
hscroll->SetId(id);
|
||||||
|
return hscroll;
|
||||||
|
}
|
||||||
|
else if(type == "VStackView")
|
||||||
|
{
|
||||||
|
auto sv = new Views::VStackView();
|
||||||
|
sv->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))
|
||||||
|
{
|
||||||
|
std::string n="min";
|
||||||
|
|
||||||
|
dict.TryGetValueAsType("Size",n);
|
||||||
|
|
||||||
|
|
||||||
|
auto myO = CreateViewFromJson(dict);
|
||||||
|
if(myO != nullptr)
|
||||||
|
{
|
||||||
|
sv->Add(szStr2size(n),myO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sv;
|
||||||
|
}
|
||||||
|
else if(type == "HStackView")
|
||||||
|
{
|
||||||
|
auto sv = new Views::HStackView();
|
||||||
|
sv->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))
|
||||||
|
{
|
||||||
|
std::string n="min";
|
||||||
|
|
||||||
|
dict.TryGetValueAsType("Size",n);
|
||||||
|
|
||||||
|
|
||||||
|
auto myO = CreateViewFromJson(dict);
|
||||||
|
if(myO != nullptr)
|
||||||
|
{
|
||||||
|
sv->Add(szStr2size(n),myO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sv;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
GUIJsonViewNotFoundEventArgs e;
|
GUIJsonViewNotFoundEventArgs e;
|
||||||
e.destView == nullptr;
|
e.destView == nullptr;
|
||||||
|
|||||||
@ -98,8 +98,8 @@ namespace Tesses::Framework::SDL2
|
|||||||
{
|
{
|
||||||
GUIMouseButtonEventArgs cea;
|
GUIMouseButtonEventArgs cea;
|
||||||
cea.button = (int)event.button.button;
|
cea.button = (int)event.button.button;
|
||||||
cea.x = event.button.x - myVisibleBounds.x;
|
cea.x = event.button.x - myBounds.x;
|
||||||
cea.y = event.button.y - myVisibleBounds.y;
|
cea.y = event.button.y - myBounds.y;
|
||||||
cea.which = event.button.which;
|
cea.which = event.button.which;
|
||||||
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,true);
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,true);
|
||||||
OnMouseDown(cea);
|
OnMouseDown(cea);
|
||||||
@ -112,8 +112,8 @@ namespace Tesses::Framework::SDL2
|
|||||||
{
|
{
|
||||||
GUIMouseButtonEventArgs cea;
|
GUIMouseButtonEventArgs cea;
|
||||||
cea.button = (int)event.button.button;
|
cea.button = (int)event.button.button;
|
||||||
cea.x = event.button.x - myVisibleBounds.x;
|
cea.x = event.button.x - myBounds.x;
|
||||||
cea.y = event.button.y - myVisibleBounds.y;
|
cea.y = event.button.y - myBounds.y;
|
||||||
cea.which = event.button.which;
|
cea.which = event.button.which;
|
||||||
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,false);
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,false);
|
||||||
OnMouseUp(cea);
|
OnMouseUp(cea);
|
||||||
|
|||||||
@ -10,6 +10,22 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
ButtonView::ButtonView(std::string text) : View(text)
|
ButtonView::ButtonView(std::string text) : View(text)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
std::pair<int,int> ButtonView::PreferedMinSize()
|
||||||
|
{
|
||||||
|
int w=-2;
|
||||||
|
int h=-2;
|
||||||
|
|
||||||
|
auto win = GetWindow();
|
||||||
|
if(win != nullptr)
|
||||||
|
{
|
||||||
|
win->normal_font->CalculateSize(text,w,h);
|
||||||
|
|
||||||
|
w += win->palette.borderSize*3;
|
||||||
|
|
||||||
|
h += win->palette.borderSize*3;
|
||||||
|
}
|
||||||
|
return std::pair<int,int>(w,h);
|
||||||
}
|
}
|
||||||
bool ButtonView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
bool ButtonView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& myVisibleBounds)
|
||||||
{
|
{
|
||||||
@ -69,7 +85,7 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
|
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};
|
SDL_Rect r2={.x=r.x,.y=r.y,.w=r.w,.h=r.h};
|
||||||
for(size_t i=0;i < 4; i++)
|
for(size_t i=0;i < win->palette.borderSize; i++)
|
||||||
{
|
{
|
||||||
SDL_RenderDrawRect(renderer,&r2);
|
SDL_RenderDrawRect(renderer,&r2);
|
||||||
r2.x++;
|
r2.x++;
|
||||||
|
|||||||
@ -21,7 +21,7 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
|
|
||||||
//we only need the y
|
//we only need the y
|
||||||
|
|
||||||
int x = r.x+checkSz+8;
|
int x = r.x+checkSz+(win->palette.borderSize*2);
|
||||||
int y = r.y+((r.h/2)-(textH/2));
|
int y = r.y+((r.h/2)-(textH/2));
|
||||||
|
|
||||||
win->normal_font->Render(renderer,x,y,text,win->palette.accent);
|
win->normal_font->Render(renderer,x,y,text,win->palette.accent);
|
||||||
@ -34,15 +34,15 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
|
|
||||||
//x=0,y=0.5, x=0.5, y=1
|
//x=0,y=0.5, x=0.5, y=1
|
||||||
|
|
||||||
int x1=checkBoxRect.x+4;
|
int x1=checkBoxRect.x+win->palette.borderSize;
|
||||||
int y1=checkBoxRect.y+4+((checkSz-8)/2);
|
int y1=checkBoxRect.y+win->palette.borderSize+((checkSz-(win->palette.borderSize*2))/2);
|
||||||
int x2=checkBoxRect.x+4+((checkSz-8)/2);
|
int x2=checkBoxRect.x+win->palette.borderSize+((checkSz-(win->palette.borderSize*2))/2);
|
||||||
int y2=checkBoxRect.y+4+(checkSz-8);
|
int y2=checkBoxRect.y+win->palette.borderSize+(checkSz-(win->palette.borderSize*8));
|
||||||
|
|
||||||
int x3=checkBoxRect.x+4+(checkSz-8);
|
int x3=checkBoxRect.x+win->palette.borderSize+(checkSz-(win->palette.borderSize*2));
|
||||||
int y3=checkBoxRect.y+4;
|
int y3=checkBoxRect.y+win->palette.borderSize;
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
{
|
{
|
||||||
SDL_RenderDrawLine(renderer,x1,y1-i,x2,y2-i);
|
SDL_RenderDrawLine(renderer,x1,y1-i,x2,y2-i);
|
||||||
SDL_RenderDrawLine(renderer,x2-i,y2,x3-i,y3);
|
SDL_RenderDrawLine(renderer,x2-i,y2,x3-i,y3);
|
||||||
|
|||||||
113
src/SDL2/Views/DropDownView.cpp
Normal file
113
src/SDL2/Views/DropDownView.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
|
||||||
|
#include "TessesFramework/SDL2/Views/DropDownView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views {
|
||||||
|
|
||||||
|
void DropDownView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
std::string text = this->text;
|
||||||
|
if(this->listView.selected > -1 && this->listView.selected < this->listView.items.size())
|
||||||
|
{
|
||||||
|
text = this->listView.items[this->listView.selected];
|
||||||
|
}
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
|
||||||
|
int textW;
|
||||||
|
int textH;
|
||||||
|
win->normal_font->CalculateSize(text,textW,textH);
|
||||||
|
|
||||||
|
int x=win->palette.borderSize*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,text,win->palette.accent);
|
||||||
|
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 < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawRect(renderer,&r2);
|
||||||
|
r2.x++;
|
||||||
|
r2.y++;
|
||||||
|
r2.w-=2;
|
||||||
|
r2.h-=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
bool DropDownView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
win->MakeActive(this);
|
||||||
|
this->popup.bounds.x = myBounds.x;
|
||||||
|
this->popup.bounds.y = myBounds.y+myBounds.h;
|
||||||
|
this->popup.bounds.w = myBounds.w;
|
||||||
|
this->popup.bounds.h = 150;
|
||||||
|
auto pu = &this->popup;
|
||||||
|
if(!this->hasSet) {
|
||||||
|
|
||||||
|
this->listView.ValueChanged += std::make_shared<FunctionalEvent<View*,GUIEventArgs&>>([pu](View* view,GUIEventArgs& args)->void {
|
||||||
|
pu->Close();
|
||||||
|
});
|
||||||
|
|
||||||
|
this->popup.SetView(&this->listView,false);
|
||||||
|
this->hasSet=true;
|
||||||
|
}
|
||||||
|
win->ShowPopup(pu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(event.type == SDL_KEYDOWN)
|
||||||
|
{
|
||||||
|
switch(event.key.keysym.sym)
|
||||||
|
{
|
||||||
|
case SDLK_UP:
|
||||||
|
{
|
||||||
|
this->listView.selected--;
|
||||||
|
if(this->listView.selected < 0 || this->listView.selected >= this->listView.items.size())
|
||||||
|
{
|
||||||
|
this->listView.selected = (int)(this->listView.items.size()-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
{
|
||||||
|
this->listView.selected++;
|
||||||
|
if(this->listView.selected < -1 || this->listView.selected >= this->listView.items.size())
|
||||||
|
{
|
||||||
|
this->listView.selected=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DropDownView::DropDownView() : View("--PLEASE SELECT ONE--")
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
std::vector<std::string>& DropDownView::GetItems()
|
||||||
|
{
|
||||||
|
return this->listView.items;
|
||||||
|
}
|
||||||
|
void DropDownView::SetIndex(int index)
|
||||||
|
{
|
||||||
|
this->listView.selected = index;
|
||||||
|
}
|
||||||
|
int DropDownView::GetIndex()
|
||||||
|
{
|
||||||
|
return this->listView.selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -55,13 +55,13 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
}
|
}
|
||||||
std::pair<int,int> EditTextView::PreferedMinSize()
|
std::pair<int,int> EditTextView::PreferedMinSize()
|
||||||
{
|
{
|
||||||
int x=-2;
|
int x=-1;
|
||||||
int y=-2;
|
int y=-1;
|
||||||
auto win = this->GetWindow();
|
auto win = this->GetWindow();
|
||||||
if(win != nullptr)
|
if(win != nullptr)
|
||||||
{
|
{
|
||||||
x=-1;
|
x=-1;
|
||||||
y=win->monospaced_font->MaxHeight()+16;
|
y=win->monospaced_font->MaxHeight()+(win->palette.borderSize*4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,13 +297,13 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
int textW=win->monospaced_font->MaxWidth()+2;
|
int textW=win->monospaced_font->MaxWidth()+2;
|
||||||
int textH=win->monospaced_font->MaxHeight();
|
int textH=win->monospaced_font->MaxHeight();
|
||||||
|
|
||||||
int noChars = (r.w-16) / textW;
|
int noChars = (r.w-(win->palette.borderSize*4)) / textW;
|
||||||
|
|
||||||
|
|
||||||
int x=0;
|
int x=0;
|
||||||
int y=(r.h/2)-((textH+16)/2);
|
int y=(r.h/2)-((textH+(win->palette.borderSize*4))/2);
|
||||||
x+=r.x+8;
|
x+=r.x+(win->palette.borderSize*2);
|
||||||
y+=r.y+8;
|
y+=r.y+(win->palette.borderSize*2);
|
||||||
|
|
||||||
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||||
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||||
@ -367,8 +367,8 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
|
SDL_SetRenderDrawColor(renderer,color.r,color.g,color.b,color.a);
|
||||||
|
|
||||||
SDL_Rect r2={.x=r.x,.y=y-4,.w=r.w,.h=textH+16};
|
SDL_Rect r2={.x=r.x,.y=y-(win->palette.borderSize*2),.w=r.w,.h=textH+16};
|
||||||
for(size_t i=0;i < 4; i++)
|
for(size_t i=0;i < win->palette.borderSize; i++)
|
||||||
{
|
{
|
||||||
SDL_RenderDrawRect(renderer,&r2);
|
SDL_RenderDrawRect(renderer,&r2);
|
||||||
r2.x++;
|
r2.x++;
|
||||||
|
|||||||
329
src/SDL2/Views/HScrollView.cpp
Normal file
329
src/SDL2/Views/HScrollView.cpp
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
|
||||||
|
#include "TessesFramework/SDL2/Views/HScrollView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
std::pair<int,int> HScrollView::PreferedMinSize()
|
||||||
|
{
|
||||||
|
return std::pair<int,int>(-1,32);
|
||||||
|
}
|
||||||
|
void HScrollView::OnValueChanged(GUIEventArgs& e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
HScrollView::HScrollView() : HScrollView(0, 0, 100)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
HScrollView::HScrollView(uint64_t value, uint64_t min, uint64_t max,uint64_t step) : View()
|
||||||
|
{
|
||||||
|
this->value = value;
|
||||||
|
this->min = min;
|
||||||
|
this->max = max;
|
||||||
|
|
||||||
|
this->step=step;
|
||||||
|
}
|
||||||
|
void HScrollView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
auto leftIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_B1STATE);
|
||||||
|
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||||
|
auto leftIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE);
|
||||||
|
|
||||||
|
auto middleIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||||
|
|
||||||
|
auto middleIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||||
|
|
||||||
|
|
||||||
|
auto rightIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_B2STATE);
|
||||||
|
|
||||||
|
auto rightIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE);
|
||||||
|
|
||||||
|
SDL_Color& leftColor = win->palette.GetBorderColor(leftIsHovering,isActive,leftIsMouseDown);
|
||||||
|
SDL_Color& leftMiddleColor = win->palette.GetBorderColor(leftIsHovering||middleIsHovering,isActive,leftIsMouseDown||middleIsMouseDown);
|
||||||
|
SDL_Color& middleColor = win->palette.GetBorderColor(middleIsHovering,isActive,middleIsMouseDown);
|
||||||
|
SDL_Color& rightMiddleColor = win->palette.GetBorderColor(rightIsHovering||middleIsHovering,isActive,rightIsMouseDown||middleIsMouseDown);
|
||||||
|
SDL_Color& rightColor = win->palette.GetBorderColor(rightIsHovering,isActive,rightIsMouseDown);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer,leftColor.r,leftColor.g,leftColor.b,leftColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+i,r.y,r.x+i,r.y+r.h); //horizontal
|
||||||
|
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,r.x,r.y+i,r.x+32,r.y+i); //horizontal
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,r.x,r.y+r.h-(1+i),r.x+32,r.y+r.h-(1+i)); //horizontal
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,leftMiddleColor.r,leftMiddleColor.g,leftMiddleColor.b,leftMiddleColor.a);
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,(r.x+32)-i,r.y,(r.x+32)-i,r.y+r.h); //horizontal
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,middleColor.r,middleColor.g,middleColor.b,middleColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+33,r.y+i,r.x+(r.w-33),r.y+i); //horizontal
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+33,r.y+r.h-(1+i),r.x+(r.w-33),r.y+r.h-(1+i)); //horizontal
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,rightColor.r,rightColor.g,rightColor.b,rightColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,(r.x+r.w)-(i+1),r.y,(r.x+r.w)-(i+1),r.y+r.h); //horizontal
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+(r.w-32),r.y+i,r.x+r.w,r.y+i); //horizontal
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+(r.w-32),r.y+r.h-(1+i),r.x+r.w,r.y+r.h-(1+i)); //horizonal
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,rightMiddleColor.r,rightMiddleColor.g,rightMiddleColor.b,rightMiddleColor.a);
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,(r.x+(r.w-32))+i,r.y,(r.x+(r.w-32))+i,r.y+r.h); //horizontal
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int y1 = 15;
|
||||||
|
int x1 = 8 + i;
|
||||||
|
|
||||||
|
int y2 = 9;
|
||||||
|
int x2 = 18 + i;
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x1+r.x,y1+r.y,x2+r.x,y2+r.y);
|
||||||
|
|
||||||
|
int y3 = 31-y1;
|
||||||
|
int y4 = 31-y2;
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x1+r.x,y3+r.y,x2+r.x,y4+r.y);
|
||||||
|
|
||||||
|
int x3 = 31-x1;
|
||||||
|
int x4 = 31-x2;
|
||||||
|
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x3+r.x+(r.w-32),y1+r.y,x4+r.x+(r.w-32),y2+r.y);
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x3+r.x+(r.w-32),y3+r.y,x4+r.x+(r.w-32),y4+r.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t width = (uint64_t)r.w - 66;
|
||||||
|
uint64_t scrollSize = 4;
|
||||||
|
uint64_t dif = max-min;
|
||||||
|
if(dif > 0)
|
||||||
|
scrollSize = width / dif;
|
||||||
|
|
||||||
|
if(scrollSize < 4) scrollSize=4;
|
||||||
|
|
||||||
|
|
||||||
|
double scroll = 0;
|
||||||
|
if(dif > 0)
|
||||||
|
scroll = (double)(value-min) / (double)dif;
|
||||||
|
|
||||||
|
uint64_t scrollX = scroll * (width-scrollSize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(scrollX > width-scrollSize) scrollX = width-scrollSize;
|
||||||
|
SDL_Rect r2={.x=(int)scrollX+r.x+32,.y=r.y+win->palette.borderSize,.w=(int)scrollSize,.h = r.h-(win->palette.borderSize*2)};
|
||||||
|
SDL_RenderFillRect(renderer,&r2);
|
||||||
|
}
|
||||||
|
bool HScrollView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
if(event.type == SDL_MOUSEMOTION)
|
||||||
|
{
|
||||||
|
bool inside = event.motion.x >= visibleBounds.x && event.motion.x < visibleBounds.x+visibleBounds.w && event.motion.y >= visibleBounds.y && event.motion.y < visibleBounds.y+visibleBounds.h;
|
||||||
|
bool hoverFlag = this->GetViewFlag(VIEWFLAG_HOVER_STATE) || this->GetViewFlag(VIEWFLAG_HOVER_B1STATE) || this->GetViewFlag(VIEWFLAG_HOVER_B2STATE);
|
||||||
|
if(inside && !hoverFlag)
|
||||||
|
{
|
||||||
|
int x = event.motion.x - myBounds.x;
|
||||||
|
if(x <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else if(x >= myBounds.w-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
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);
|
||||||
|
} else if(inside) {
|
||||||
|
int x = event.motion.x - myBounds.x;
|
||||||
|
if(x <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else if(x >= myBounds.w-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,true);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||||
|
{
|
||||||
|
int x = event.motion.x - myBounds.x;
|
||||||
|
if(x <= 32)
|
||||||
|
{
|
||||||
|
value = min;
|
||||||
|
}
|
||||||
|
else if(x >= myBounds.w-32)
|
||||||
|
{
|
||||||
|
value=max;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint64_t width = (uint64_t)myBounds.w - 66;
|
||||||
|
uint64_t x2 = x-33;
|
||||||
|
|
||||||
|
double off = (double)x2 / (double)width;
|
||||||
|
|
||||||
|
value = round((max-min)*off)+min;
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(event.type == SDL_MOUSEBUTTONDOWN)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.y;
|
||||||
|
cea.which = event.button.which;
|
||||||
|
if(cea.x <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE,true);
|
||||||
|
}
|
||||||
|
else if(cea.x >= myBounds.w-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE,true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,true);
|
||||||
|
|
||||||
|
uint64_t width = (uint64_t)myBounds.w - 66;
|
||||||
|
uint64_t x2 = cea.x-33;
|
||||||
|
|
||||||
|
double off = (double)x2 / (double)width;
|
||||||
|
|
||||||
|
value = round((max-min)*off)+min;
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
}
|
||||||
|
OnMouseDown(cea);
|
||||||
|
this->MouseDown.Invoke(this,cea);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(event.type == SDL_MOUSEBUTTONUP)
|
||||||
|
{
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.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,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE))
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.y;
|
||||||
|
cea.which = event.button.which;
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE,false);
|
||||||
|
OnMouseUp(cea);
|
||||||
|
this->MouseUp.Invoke(this,cea);
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
OnClick(cea2);
|
||||||
|
this->Click.Invoke(this,cea2);
|
||||||
|
this->value -= step;
|
||||||
|
if(this->value < min) this->value=min;
|
||||||
|
if(this->value >= max) this->value=min;
|
||||||
|
OnValueChanged(cea2);
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE))
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.y;
|
||||||
|
cea.which = event.button.which;
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE,false);
|
||||||
|
OnMouseUp(cea);
|
||||||
|
this->MouseUp.Invoke(this,cea);
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
OnClick(cea2);
|
||||||
|
this->Click.Invoke(this,cea2);
|
||||||
|
this->value += step;
|
||||||
|
if(this->value > max) this->value=max;
|
||||||
|
OnValueChanged(cea2);
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return View::OnEvent(event,myBounds,visibleBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
273
src/SDL2/Views/HStackView.cpp
Normal file
273
src/SDL2/Views/HStackView.cpp
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "TessesFramework/SDL2/Views/HStackView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
void HStackView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
int numberOfCells = 0;
|
||||||
|
int freeWidth = r.w;
|
||||||
|
std::vector<int> sizes;
|
||||||
|
sizes.resize(this->items.size());
|
||||||
|
|
||||||
|
freeWidth -= (this->items.size() - 1) * this->spacing;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first > 0)
|
||||||
|
{
|
||||||
|
//static size
|
||||||
|
sizes[i] = this->items[i].first;
|
||||||
|
freeWidth-= this->items[i].first;
|
||||||
|
}
|
||||||
|
else if(this->items[i].first == 0)
|
||||||
|
{
|
||||||
|
auto prefered = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(prefered.first > 0)
|
||||||
|
{
|
||||||
|
sizes[i] = prefered.first;
|
||||||
|
freeWidth -= prefered.first;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sizes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numberOfCells -= this->items[i].first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cellSize = numberOfCells == 0 ? 0 : freeWidth / numberOfCells;
|
||||||
|
|
||||||
|
|
||||||
|
for(int i = 0; i < this->items.size();i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first < 0)
|
||||||
|
{
|
||||||
|
int myWidth =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
auto minSz = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(minSz.first > myWidth) {
|
||||||
|
sizes[i] = minSz.first;
|
||||||
|
freeWidth-= minSz.first;
|
||||||
|
numberOfCells -= -(this->items[i].first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cellSize = numberOfCells == 0 ? 0 : freeWidth/ numberOfCells;
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(i > 0) x += spacing;
|
||||||
|
|
||||||
|
if(sizes[i] == 0)
|
||||||
|
{
|
||||||
|
int myWidth =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x =x,
|
||||||
|
.y=0,
|
||||||
|
.w=myWidth,
|
||||||
|
.h=r.h
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
theirBounds.x += r.x;
|
||||||
|
theirBounds.y += r.y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnDraw(this->items[i].second.first,renderer, theirBounds);
|
||||||
|
x+=myWidth;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x =x,
|
||||||
|
.y=0,
|
||||||
|
.w=sizes[i],
|
||||||
|
.h=r.h
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
theirBounds.x += r.x;
|
||||||
|
theirBounds.y += r.y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnDraw(this->items[i].second.first,renderer, theirBounds);
|
||||||
|
x+=sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool HStackView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
int numberOfCells = 0;
|
||||||
|
int freeWidth = myBounds.w;
|
||||||
|
std::vector<int> sizes;
|
||||||
|
sizes.resize(this->items.size());
|
||||||
|
|
||||||
|
|
||||||
|
freeWidth -= (this->items.size() - 1) * this->spacing;
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first > 0)
|
||||||
|
{
|
||||||
|
//static size
|
||||||
|
sizes[i] = this->items[i].first;
|
||||||
|
freeWidth-= this->items[i].first;
|
||||||
|
}
|
||||||
|
else if(this->items[i].first == 0)
|
||||||
|
{
|
||||||
|
auto prefered = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(prefered.first > 0)
|
||||||
|
{
|
||||||
|
sizes[i] = prefered.first;
|
||||||
|
freeWidth -= prefered.first;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sizes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numberOfCells -= this->items[i].first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cellSize = numberOfCells == 0 ? 0 : freeWidth/ numberOfCells;
|
||||||
|
|
||||||
|
for(int i = 0; i < this->items.size();i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first < 0)
|
||||||
|
{
|
||||||
|
int myWidth =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
auto minSz = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(minSz.first > myWidth) {
|
||||||
|
sizes[i] = minSz.first;
|
||||||
|
myWidth -= minSz.first;
|
||||||
|
numberOfCells -= -(this->items[i].first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
numberOfCells == 0 ? 0 : freeWidth/ numberOfCells;
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(i > 0) x += spacing;
|
||||||
|
if(sizes[i] == 0)
|
||||||
|
{
|
||||||
|
int myWidth =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
auto minSz = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(minSz.first > myWidth) myWidth = minSz.first;
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x = x,
|
||||||
|
.y=0,
|
||||||
|
.w=myWidth,
|
||||||
|
.h=myBounds.h
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_Rect theirVisibleBounds = theirBounds;
|
||||||
|
theirVisibleBounds.x += visibleBounds.x;
|
||||||
|
theirVisibleBounds.y += visibleBounds.y;
|
||||||
|
|
||||||
|
theirBounds.x += myBounds.x;
|
||||||
|
theirBounds.y += myBounds.y;
|
||||||
|
Clipper::ClipRect(theirVisibleBounds, visibleBounds);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnEvent(this->items[i].second.first,event,theirBounds,theirVisibleBounds);
|
||||||
|
|
||||||
|
x+=myWidth;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x = x,
|
||||||
|
.y=0,
|
||||||
|
.w=sizes[i],
|
||||||
|
.h=myBounds.h
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_Rect theirVisibleBounds = theirBounds;
|
||||||
|
theirVisibleBounds.x += visibleBounds.x;
|
||||||
|
theirVisibleBounds.y += visibleBounds.y;
|
||||||
|
|
||||||
|
theirBounds.x += myBounds.x;
|
||||||
|
theirBounds.y += myBounds.y;
|
||||||
|
Clipper::ClipRect(theirVisibleBounds, visibleBounds);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnEvent(this->items[i].second.first,event,theirBounds,theirVisibleBounds);
|
||||||
|
|
||||||
|
x+=sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HStackView::HStackView() : ContainerView()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void HStackView::Add(int sz, View* view, bool owns)
|
||||||
|
{
|
||||||
|
this->items.push_back(std::pair<int,std::pair<View*,bool>>(sz,std::pair<View*,bool>(view,owns)));
|
||||||
|
this->AssignChildParentToThis(view);
|
||||||
|
}
|
||||||
|
void HStackView::Remove(View* view)
|
||||||
|
{
|
||||||
|
for(auto index = this->items.begin(); index < this->items.end(); index++)
|
||||||
|
{
|
||||||
|
if(index->second.first == view)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(index->second.first != nullptr && index->second.second)
|
||||||
|
delete view;
|
||||||
|
this->items.erase(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void HStackView::Clear()
|
||||||
|
{
|
||||||
|
for(auto& item : this->items)
|
||||||
|
if(item.second.second && item.second.first != nullptr) delete item.second.first;
|
||||||
|
items = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t HStackView::ViewCount()
|
||||||
|
{
|
||||||
|
return this->items.size();
|
||||||
|
}
|
||||||
|
View* HStackView::GetViewAt(size_t index)
|
||||||
|
{
|
||||||
|
return this->items.at(index).second.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
HStackView::~HStackView()
|
||||||
|
{
|
||||||
|
for(auto& item : this->items)
|
||||||
|
if(item.second.second && item.second.first != nullptr) delete item.second.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -5,7 +5,7 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
void LabelView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
void LabelView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
{
|
{
|
||||||
auto win =this->GetWindow();
|
auto win =this->GetWindow();
|
||||||
win->normal_font->Render(renderer,r.x+4,r.y+4,text,win->palette.accent);
|
win->normal_font->Render(renderer,r.x+win->palette.borderSize,r.y+win->palette.borderSize,text,win->palette.accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelView::LabelView() : View()
|
LabelView::LabelView() : View()
|
||||||
|
|||||||
178
src/SDL2/Views/MultilineEditTextView.cpp
Normal file
178
src/SDL2/Views/MultilineEditTextView.cpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "TessesFramework/SDL2/Views/MultilineEditTextView.hpp"
|
||||||
|
#include "TessesFramework/Http/HttpUtils.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
void MultilineEditTextView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
//1 |
|
||||||
|
|
||||||
|
// 9 |
|
||||||
|
//10 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
bool MultilineEditTextView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
MultilineEditTextView::MultilineEditTextView() :MultilineEditTextView(std::string())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
MultilineEditTextView::MultilineEditTextView(std::string hint) : View()
|
||||||
|
{
|
||||||
|
this->hint = hint;
|
||||||
|
}
|
||||||
|
std::string MultilineEditTextView::GetHint()
|
||||||
|
{
|
||||||
|
return this->hint;
|
||||||
|
}
|
||||||
|
void MultilineEditTextView::SetHint(std::string hint)
|
||||||
|
{
|
||||||
|
this->hint = hint;
|
||||||
|
}
|
||||||
|
std::string MultilineEditTextView::GetText()
|
||||||
|
{
|
||||||
|
if(this->lines.empty()) return {};
|
||||||
|
std::string text = this->lines.front();
|
||||||
|
for(size_t i = 1; i < this->lines.size(); i++)
|
||||||
|
{
|
||||||
|
text.push_back('\n');
|
||||||
|
text.append(this->lines[i]);
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
void MultilineEditTextView::SetText(std::string text)
|
||||||
|
{
|
||||||
|
lines.clear();
|
||||||
|
std::string line = "";
|
||||||
|
for(auto c : text)
|
||||||
|
{
|
||||||
|
if(c == '\n') {
|
||||||
|
lines.push_back(line);
|
||||||
|
line = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
line += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!line.empty()) lines.push_back(line);
|
||||||
|
|
||||||
|
this->cursorPos.x=0;
|
||||||
|
this->cursorPos.y=0;
|
||||||
|
this->cursorEnd.x=-1;
|
||||||
|
this->cursorEnd.y=-1;
|
||||||
|
}
|
||||||
|
void MultilineEditTextView::TypeText(std::string text)
|
||||||
|
{
|
||||||
|
|
||||||
|
SDL_Point cursorBegin = this->cursorPos;
|
||||||
|
SDL_Point cursorEnd = this->cursorEnd;
|
||||||
|
if(cursorBegin.y > cursorEnd.y || ((cursorBegin.y == cursorEnd.y) && (cursorBegin.x > cursorEnd.x)))
|
||||||
|
{
|
||||||
|
cursorBegin.y ^= cursorEnd.y;
|
||||||
|
cursorEnd.y ^= cursorBegin.y;
|
||||||
|
cursorBegin.y ^= cursorEnd.y;
|
||||||
|
|
||||||
|
cursorBegin.x ^= cursorEnd.x;
|
||||||
|
cursorEnd.x ^= cursorBegin.x;
|
||||||
|
cursorBegin.x ^= cursorEnd.x;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
if(cursorEnd != std::string::npos && cursorEnd <= this->text.size())
|
||||||
|
{
|
||||||
|
this->text.erase(cursorBegin,cursorEnd-cursorBegin);
|
||||||
|
this->text.insert(cursorBegin,text);
|
||||||
|
}
|
||||||
|
else if(cursorBegin <= this->text.size()) {
|
||||||
|
this->text.insert(cursorBegin,text);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this->cursorPos = cursorBegin+text.size();
|
||||||
|
this->cursorEnd = std::string::npos;*/
|
||||||
|
|
||||||
|
if(cursorEnd.y != -1 && cursorEnd.x != -1)
|
||||||
|
{
|
||||||
|
int line = cursorBegin.y;
|
||||||
|
for(int y = cursorBegin.y; y <= cursorEnd.y && y < lines.size(); y++)
|
||||||
|
{
|
||||||
|
if(y == cursorBegin.y && y == cursorEnd.y && cursorBegin.x == 0 && cursorEnd.x == this->lines[y].size()-1)
|
||||||
|
{
|
||||||
|
this->lines.erase(this->lines.begin()+line);
|
||||||
|
}
|
||||||
|
else if(y == cursorBegin.y && y == cursorEnd.y)
|
||||||
|
{
|
||||||
|
this->lines[line]=this->lines[line].substr(0,cursorBegin.x) + this->lines[line].substr(cursorEnd.x);
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
else if(y == cursorBegin.y && cursorBegin.x == 0)
|
||||||
|
{
|
||||||
|
this->lines.erase(this->lines.begin()+line);
|
||||||
|
}
|
||||||
|
else if(y == cursorBegin.y)
|
||||||
|
{
|
||||||
|
this->lines[line]=this->lines[line].substr(0,cursorBegin.x);
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
else if(y > cursorBegin.y && y < cursorEnd.y)
|
||||||
|
{
|
||||||
|
this->lines.erase(this->lines.begin()+line);
|
||||||
|
}
|
||||||
|
else if(y == cursorEnd.y && cursorEnd.x < this->lines[line].size()-1)
|
||||||
|
{
|
||||||
|
this->lines[line]=this->lines[line].substr(cursorBegin.x);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->lines.erase(this->lines.begin()+line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auto mylines = Http::HttpUtils::SplitString(text,"\n");
|
||||||
|
|
||||||
|
if(!mylines.empty())
|
||||||
|
{
|
||||||
|
if(cursorBegin.y < this->lines.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
if(cursorBegin.x > 0)
|
||||||
|
{
|
||||||
|
mylines[0] = this->lines[cursorBegin.y].substr(0,cursorBegin.x) + mylines[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cursorBegin.x < this->lines[cursorBegin.y].size())
|
||||||
|
{
|
||||||
|
mylines.back() += this->lines[cursorBegin.y].substr(cursorBegin.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->lines.erase(this->lines.begin()+cursorBegin.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for(auto& item : mylines)
|
||||||
|
{
|
||||||
|
this->lines.insert(this->lines.begin()+cursorBegin.y,{item});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this->cursorPos = cursorBegin;
|
||||||
|
this->cursorEnd = {.x=-1,.y=-1};
|
||||||
|
}
|
||||||
|
std::pair<int,int> MultilineEditTextView::PreferedMinSize()
|
||||||
|
{
|
||||||
|
return std::pair<int,int>(128,128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -18,10 +18,10 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
auto win = this->GetWindow();
|
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_SetRenderDrawColor(renderer,win->palette.borderColor.r,win->palette.borderColor.g,win->palette.borderColor.b,win->palette.borderColor.a);
|
||||||
|
|
||||||
SDL_Rect r2={.x=rect.x,.y=rect.y,.w=rect.w,.h=rect.h};
|
SDL_Rect r2={.x=rect.x,.y=rect.y,.w=rect.w,.h=rect.h};
|
||||||
for(size_t i=0;i < 4; i++)
|
for(size_t i=0;i < win->palette.borderSize; i++)
|
||||||
{
|
{
|
||||||
SDL_RenderDrawRect(renderer,&r2);
|
SDL_RenderDrawRect(renderer,&r2);
|
||||||
r2.x++;
|
r2.x++;
|
||||||
@ -30,8 +30,8 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
r2.h-=2;
|
r2.h-=2;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = (int)((rect.w-8)*(this->value/100.0));
|
auto res = (int)((rect.w-(win->palette.borderSize*2))*(this->value/100.0));
|
||||||
r2={.x=rect.x+4,.y=rect.y+4,.w=res,.h=rect.h-8};
|
r2={.x=rect.x+win->palette.borderSize,.y=rect.y+win->palette.borderSize,.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_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||||
SDL_RenderFillRect(renderer,&r2);
|
SDL_RenderFillRect(renderer,&r2);
|
||||||
}
|
}
|
||||||
|
|||||||
444
src/SDL2/Views/ScrollableTextListView.cpp
Normal file
444
src/SDL2/Views/ScrollableTextListView.cpp
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
|
||||||
|
#include "TessesFramework/SDL2/Views/ScrollableTextListView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
ScrollableTextListView::ScrollableTextListView() : View()
|
||||||
|
{
|
||||||
|
this->firstIndex=0;
|
||||||
|
this->selected=-1;
|
||||||
|
}
|
||||||
|
bool ScrollableTextListView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
auto item_height = win->normal_font->MaxHeight()+(win->palette.borderSize*2);
|
||||||
|
auto no_items = (myBounds.h-(win->palette.borderSize*2)) / item_height;
|
||||||
|
auto max_items = no_items;
|
||||||
|
|
||||||
|
if(this->firstIndex + no_items > this->items.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
no_items = this->items.size()-this->firstIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(event.type == SDL_KEYDOWN)
|
||||||
|
{
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_ISACTIVE))
|
||||||
|
{
|
||||||
|
switch(event.key.keysym.sym)
|
||||||
|
{
|
||||||
|
case SDLK_RETURN:
|
||||||
|
{
|
||||||
|
|
||||||
|
GUIEventArgs e;
|
||||||
|
if(this->selected > -1)
|
||||||
|
this->ValueChanged.Invoke(this,e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDLK_HOME:
|
||||||
|
this->selected=0;
|
||||||
|
this->firstIndex=0;
|
||||||
|
break;
|
||||||
|
case SDLK_END:
|
||||||
|
this->selected = (int)(this->items.size()-1);
|
||||||
|
|
||||||
|
this->firstIndex= this->selected-(this->selected % max_items);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
this->selected++;
|
||||||
|
if(this->selected < -1 || this->selected >= this->items.size())
|
||||||
|
{
|
||||||
|
this->selected=0;
|
||||||
|
}
|
||||||
|
this->firstIndex= this->selected-(this->selected % max_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-(this->selected % max_items);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event.type == SDL_MOUSEMOTION)
|
||||||
|
{
|
||||||
|
bool inside = event.motion.x >= visibleBounds.x && event.motion.x < visibleBounds.x+visibleBounds.w && event.motion.y >= visibleBounds.y && event.motion.y < visibleBounds.y+visibleBounds.h;
|
||||||
|
bool hoverFlag = this->GetViewFlag(VIEWFLAG_HOVER_STATE) || this->GetViewFlag(VIEWFLAG_HOVER_B1STATE) || this->GetViewFlag(VIEWFLAG_HOVER_B2STATE);
|
||||||
|
if(inside && !hoverFlag)
|
||||||
|
{
|
||||||
|
int y = event.motion.y - myBounds.y;
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
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);
|
||||||
|
} else if(inside) {
|
||||||
|
int y = event.motion.y - myBounds.y;
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,true);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||||
|
{
|
||||||
|
int y = event.motion.y - myBounds.y;
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
this->firstIndex = 0;
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
uint64_t count = max_items == 0 ? 0 : this->items.size() / max_items;
|
||||||
|
|
||||||
|
if((items.size() % max_items) == 0) count--;
|
||||||
|
|
||||||
|
this->firstIndex = count*max_items;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint64_t height = (uint64_t)myBounds.h - 66;
|
||||||
|
uint64_t y2 = y-33;
|
||||||
|
|
||||||
|
double off = (double)y2 / (double)height;
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t count = max_items == 0 ? 0 : this->items.size() / max_items;
|
||||||
|
if((items.size() % max_items) == 0) count--;
|
||||||
|
|
||||||
|
this->firstIndex = round(off*count) * max_items;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(event.type == SDL_MOUSEBUTTONDOWN)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
int x= event.button.x - myBounds.x;
|
||||||
|
int y = event.button.y - myBounds.y;
|
||||||
|
|
||||||
|
if(x >= myBounds.w-32)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE,true);
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE,true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,true);
|
||||||
|
|
||||||
|
uint64_t height = (uint64_t)myBounds.h - 66;
|
||||||
|
uint64_t y2 = y-33;
|
||||||
|
|
||||||
|
double off = (double)y2 / (double)height;
|
||||||
|
|
||||||
|
uint64_t count = max_items == 0 ? 0 : this->items.size() / max_items;
|
||||||
|
if((items.size() % max_items) == 0) count--;
|
||||||
|
|
||||||
|
this->firstIndex = round(off*count) * max_items;
|
||||||
|
//value = round((max-min)*off)+min;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(event.type == SDL_MOUSEBUTTONUP)
|
||||||
|
{
|
||||||
|
int x= event.button.x - myBounds.x;
|
||||||
|
if(x < myBounds.w-32 && event.button.x >= (visibleBounds.x+win->palette.borderSize) && event.button.y >= (visibleBounds.y+win->palette.borderSize) && event.button.y < (visibleBounds.y+visibleBounds.h)-(win->palette.borderSize*2))
|
||||||
|
{
|
||||||
|
win->MakeActive(this);
|
||||||
|
auto myRealY=event.button.y - (myBounds.y+win->palette.borderSize);
|
||||||
|
auto yThing = myRealY / item_height;
|
||||||
|
|
||||||
|
if(yThing < no_items)
|
||||||
|
{
|
||||||
|
auto high= yThing+this->firstIndex;
|
||||||
|
this->selected = (int)high;
|
||||||
|
GUIEventArgs e;
|
||||||
|
this->ValueChanged.Invoke(this,e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||||
|
{
|
||||||
|
|
||||||
|
win->MakeActive(this);
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE))
|
||||||
|
{
|
||||||
|
|
||||||
|
win->MakeActive(this);
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE,false);
|
||||||
|
|
||||||
|
//this->value -= step;
|
||||||
|
//if(this->value < min) this->value=min;
|
||||||
|
//if(this->value >= max) this->value=min;
|
||||||
|
//OnValueChanged(cea2);
|
||||||
|
//this->ValueChanged.Invoke(this,cea2);
|
||||||
|
|
||||||
|
uint64_t count = max_items == 0 ? 0 : this->items.size() / max_items;
|
||||||
|
|
||||||
|
if((items.size() % max_items) == 0) count--;
|
||||||
|
|
||||||
|
auto c = max_items == 0 ? 0 : (this->firstIndex / max_items);
|
||||||
|
c--;
|
||||||
|
if(c > count) c = 0;
|
||||||
|
this->firstIndex = c * max_items;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE))
|
||||||
|
{
|
||||||
|
|
||||||
|
win->MakeActive(this);
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE,false);
|
||||||
|
|
||||||
|
uint64_t count = max_items == 0 ? 0 : this->items.size() / max_items;
|
||||||
|
|
||||||
|
if((items.size() % max_items) == 0) count--;
|
||||||
|
|
||||||
|
auto c = max_items == 0 ? 0 : (this->firstIndex / max_items);
|
||||||
|
c++;
|
||||||
|
if(c > count) c = count;
|
||||||
|
this->firstIndex = c * max_items;
|
||||||
|
//this->value += step;
|
||||||
|
//if(this->value > max) this->value=max;
|
||||||
|
//OnValueChanged(cea2);
|
||||||
|
//this->ValueChanged.Invoke(this,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return View::OnEvent(event,myBounds,visibleBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScrollableTextListView::OnDraw(SDL_Renderer* renderer,SDL_Rect& rect)
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
auto item_height = win->normal_font->MaxHeight()+(win->palette.borderSize*2);
|
||||||
|
auto no_items = (rect.h-(win->palette.borderSize*2)) / item_height;
|
||||||
|
auto max_items = no_items;
|
||||||
|
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->firstIndex + no_items > this->items.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
no_items = this->items.size()-this->firstIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect _r2={.x=rect.x,.y=rect.y,.w=rect.w-32,.h=rect.h};
|
||||||
|
for(size_t i=0;i < win->palette.borderSize; 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+win->palette.borderSize,.y=rect.y+win->palette.borderSize+(item_height*i),.w=rect.w-(win->palette.borderSize*2)-32,.h=item_height};
|
||||||
|
SDL_RenderFillRect(renderer,&r2);
|
||||||
|
win->normal_font->Render(renderer,rect.x+(win->palette.borderSize*3),(rect.y+(win->palette.borderSize*3))+(item_height*i),this->items[realI],color);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
win->normal_font->Render(renderer,rect.x+(win->palette.borderSize*3),(rect.y+(win->palette.borderSize*3))+(item_height*i),this->items[realI],win->palette.accent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto scrollX = (rect.w-32)+rect.x;
|
||||||
|
auto topIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_B1STATE);
|
||||||
|
|
||||||
|
auto topIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE);
|
||||||
|
|
||||||
|
auto middleIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||||
|
|
||||||
|
auto middleIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||||
|
|
||||||
|
|
||||||
|
auto bottomIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_B2STATE);
|
||||||
|
|
||||||
|
auto bottomIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE);
|
||||||
|
|
||||||
|
SDL_Color& topcolor = win->palette.GetBorderColor(topIsHovering,isActive,topIsMouseDown);
|
||||||
|
SDL_Color& topMiddleColor = win->palette.GetBorderColor(topIsHovering||middleIsHovering,isActive,topIsMouseDown||middleIsMouseDown);
|
||||||
|
SDL_Color& middleColor = win->palette.GetBorderColor(middleIsHovering,isActive,middleIsMouseDown);
|
||||||
|
SDL_Color& bottomMiddleColor = win->palette.GetBorderColor(bottomIsHovering||middleIsHovering,isActive,bottomIsMouseDown||middleIsMouseDown);
|
||||||
|
SDL_Color& bottomColor = win->palette.GetBorderColor(bottomIsHovering,isActive,bottomIsMouseDown);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer,topcolor.r,topcolor.g,topcolor.b,topcolor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX,rect.y+i,scrollX+32,rect.y+i);
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX+i,rect.y,scrollX+i,rect.y+32);
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX+32-(1+i),rect.y,scrollX+32-(1+i),rect.y+32);
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,topMiddleColor.r,topMiddleColor.g,topMiddleColor.b,topMiddleColor.a);
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX,(rect.y+32)-i,scrollX+32,(rect.y+32)-i);
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,middleColor.r,middleColor.g,middleColor.b,middleColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX+i,rect.y+33,scrollX+i,rect.y+(rect.h-33));
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX+32-(1+i),rect.y+33,scrollX+32-(1+i),rect.y+(rect.h-33));
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,bottomColor.r,bottomColor.g,bottomColor.b,bottomColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX,(rect.y+rect.h)-(i+1),scrollX+32,(rect.y+rect.h)-(i+1));
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX+i,rect.y+(rect.h-32),scrollX+i,rect.y+rect.h);
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX+32-(1+i),rect.y+(rect.h-32),scrollX+32-(1+i),rect.y+rect.h);
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,bottomMiddleColor.r,bottomMiddleColor.g,bottomMiddleColor.b,bottomMiddleColor.a);
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,scrollX,(rect.y+(rect.h-32))+i,scrollX+32,(rect.y+(rect.h-32))+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int x1 = 15;
|
||||||
|
int y1 = 8 + i;
|
||||||
|
|
||||||
|
int x2 = 9;
|
||||||
|
int y2 = 18 + i;
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x1+scrollX,y1+rect.y,x2+scrollX,y2+rect.y);
|
||||||
|
|
||||||
|
int x3 = 31-x1;
|
||||||
|
int x4 = 31-x2;
|
||||||
|
SDL_RenderDrawLine(renderer,x3+scrollX,y1+rect.y,x4+scrollX,y2+rect.y);
|
||||||
|
|
||||||
|
int y3 = 31-y1;
|
||||||
|
int y4 = 31-y2;
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x1+scrollX,y3+rect.y+(rect.h-32),x2+scrollX,y4+rect.y+(rect.h-32));
|
||||||
|
SDL_RenderDrawLine(renderer,x3+scrollX,y3+rect.y+(rect.h-32),x4+scrollX,y4+rect.y+(rect.h-32));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t height = (uint64_t)rect.h - 66;
|
||||||
|
uint64_t scrollSize = 4;
|
||||||
|
uint64_t count = max_items == 0 ? 0 : this->items.size() / max_items;
|
||||||
|
|
||||||
|
if((items.size() % max_items) == 0) count--;
|
||||||
|
|
||||||
|
if(count > 0)
|
||||||
|
scrollSize = height / count;
|
||||||
|
|
||||||
|
if(scrollSize < 4) scrollSize=4;
|
||||||
|
|
||||||
|
|
||||||
|
double scroll = 0;
|
||||||
|
if(count > 0 && max_items > 0)
|
||||||
|
scroll = (double)(this->firstIndex / max_items) / (double)count;
|
||||||
|
|
||||||
|
uint64_t scrollY = scroll * (height-scrollSize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(scrollY > height-scrollSize) scrollY = height-scrollSize;
|
||||||
|
SDL_Rect r2={.x=scrollX+win->palette.borderSize,.y=(int)scrollY+rect.y+32,.w = 32-(win->palette.borderSize*2),.h=(int)scrollSize};
|
||||||
|
SDL_RenderFillRect(renderer,&r2);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -12,8 +12,8 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
bool TextListView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
bool TextListView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
{
|
{
|
||||||
auto win = this->GetWindow();
|
auto win = this->GetWindow();
|
||||||
auto item_height = win->normal_font->MaxHeight()+8;
|
auto item_height = win->normal_font->MaxHeight()+(win->palette.borderSize*2);
|
||||||
auto no_items = (myBounds.h-8) / item_height;
|
auto no_items = (myBounds.h-(win->palette.borderSize*2)) / item_height;
|
||||||
|
|
||||||
if(this->items.size() > no_items)
|
if(this->items.size() > no_items)
|
||||||
{
|
{
|
||||||
@ -65,10 +65,10 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
if(event.type == SDL_MOUSEBUTTONUP && event.button.x >= (visibleBounds.x+win->palette.borderSize) && event.button.x < (visibleBounds.x+visibleBounds.w)-(win->palette.borderSize*2) && event.button.y >= (visibleBounds.y+win->palette.borderSize) && event.button.y < (visibleBounds.y+visibleBounds.h)-(win->palette.borderSize*2))
|
||||||
{
|
{
|
||||||
win->MakeActive(this);
|
win->MakeActive(this);
|
||||||
auto myRealY=event.button.y - (myBounds.y+4);
|
auto myRealY=event.button.y - (myBounds.y+win->palette.borderSize);
|
||||||
auto yThing = myRealY / item_height;
|
auto yThing = myRealY / item_height;
|
||||||
|
|
||||||
if(yThing < no_items)
|
if(yThing < no_items)
|
||||||
@ -84,8 +84,8 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
void TextListView::OnDraw(SDL_Renderer* renderer,SDL_Rect& rect)
|
void TextListView::OnDraw(SDL_Renderer* renderer,SDL_Rect& rect)
|
||||||
{
|
{
|
||||||
auto win = this->GetWindow();
|
auto win = this->GetWindow();
|
||||||
auto item_height = win->normal_font->MaxHeight()+8;
|
auto item_height = win->normal_font->MaxHeight()+(win->palette.borderSize*2);
|
||||||
auto no_items = (rect.h-8) / item_height;
|
auto no_items = (rect.h-(win->palette.borderSize*2)) / item_height;
|
||||||
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
auto isHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||||
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||||
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
auto isMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||||
@ -112,7 +112,7 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_Rect r2={.x=rect.x,.y=rect.y,.w=rect.w,.h=rect.h};
|
SDL_Rect r2={.x=rect.x,.y=rect.y,.w=rect.w,.h=rect.h};
|
||||||
for(size_t i=0;i < 4; i++)
|
for(size_t i=0;i < win->palette.borderSize; i++)
|
||||||
{
|
{
|
||||||
SDL_RenderDrawRect(renderer,&r2);
|
SDL_RenderDrawRect(renderer,&r2);
|
||||||
r2.x++;
|
r2.x++;
|
||||||
@ -127,12 +127,12 @@ namespace Tesses::Framework::SDL2::Views
|
|||||||
if(realI == this->selected)
|
if(realI == this->selected)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
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_Rect r2={.x=rect.x+win->palette.borderSize,.y=rect.y+win->palette.borderSize+(item_height*i),.w=rect.w-(win->palette.borderSize*2),.h=item_height};
|
||||||
SDL_RenderFillRect(renderer,&r2);
|
SDL_RenderFillRect(renderer,&r2);
|
||||||
win->normal_font->Render(renderer,rect.x+12,(rect.y+12)+(item_height*i),this->items[realI],color);
|
win->normal_font->Render(renderer,rect.x+(win->palette.borderSize*3),(rect.y+(win->palette.borderSize*3))+(item_height*i),this->items[realI],color);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
win->normal_font->Render(renderer,rect.x+12,(rect.y+12)+(item_height*i),this->items[realI],win->palette.accent);
|
win->normal_font->Render(renderer,rect.x+(win->palette.borderSize*3),(rect.y+(win->palette.borderSize*3))+(item_height*i),this->items[realI],win->palette.accent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
322
src/SDL2/Views/VScrollView.cpp
Normal file
322
src/SDL2/Views/VScrollView.cpp
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
|
||||||
|
#include "TessesFramework/SDL2/Views/VScrollView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
std::pair<int,int> VScrollView::PreferedMinSize()
|
||||||
|
{
|
||||||
|
return std::pair<int,int>(32,-1);
|
||||||
|
}
|
||||||
|
void VScrollView::OnValueChanged(GUIEventArgs& e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
VScrollView::VScrollView() : VScrollView(0, 0, 100)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
VScrollView::VScrollView(uint64_t value, uint64_t min, uint64_t max,uint64_t step) : View()
|
||||||
|
{
|
||||||
|
this->value = value;
|
||||||
|
this->min = min;
|
||||||
|
this->max = max;
|
||||||
|
|
||||||
|
this->step=step;
|
||||||
|
}
|
||||||
|
void VScrollView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
auto win = this->GetWindow();
|
||||||
|
auto topIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_B1STATE);
|
||||||
|
auto isActive = this->GetViewFlag(VIEWFLAG_ISACTIVE);
|
||||||
|
auto topIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE);
|
||||||
|
|
||||||
|
auto middleIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_STATE);
|
||||||
|
|
||||||
|
auto middleIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE);
|
||||||
|
|
||||||
|
|
||||||
|
auto bottomIsHovering = this->GetViewFlag(VIEWFLAG_HOVER_B2STATE);
|
||||||
|
|
||||||
|
auto bottomIsMouseDown = this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE);
|
||||||
|
|
||||||
|
SDL_Color& topcolor = win->palette.GetBorderColor(topIsHovering,isActive,topIsMouseDown);
|
||||||
|
SDL_Color& topMiddleColor = win->palette.GetBorderColor(topIsHovering||middleIsHovering,isActive,topIsMouseDown||middleIsMouseDown);
|
||||||
|
SDL_Color& middleColor = win->palette.GetBorderColor(middleIsHovering,isActive,middleIsMouseDown);
|
||||||
|
SDL_Color& bottomMiddleColor = win->palette.GetBorderColor(bottomIsHovering||middleIsHovering,isActive,bottomIsMouseDown||middleIsMouseDown);
|
||||||
|
SDL_Color& bottomColor = win->palette.GetBorderColor(bottomIsHovering,isActive,bottomIsMouseDown);
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer,topcolor.r,topcolor.g,topcolor.b,topcolor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x,r.y+i,r.x+r.w,r.y+i);
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+i,r.y,r.x+i,r.y+32);
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+r.w-(1+i),r.y,r.x+r.w-(1+i),r.y+32);
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,topMiddleColor.r,topMiddleColor.g,topMiddleColor.b,topMiddleColor.a);
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x,(r.y+32)-i,r.x+r.w,(r.y+32)-i);
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,middleColor.r,middleColor.g,middleColor.b,middleColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+i,r.y+33,r.x+i,r.y+(r.h-33));
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+r.w-(1+i),r.y+33,r.x+r.w-(1+i),r.y+(r.h-33));
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,bottomColor.r,bottomColor.g,bottomColor.b,bottomColor.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x,(r.y+r.h)-(i+1),r.x+r.w,(r.y+r.h)-(i+1));
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+i,r.y+(r.h-32),r.x+i,r.y+r.h);
|
||||||
|
SDL_RenderDrawLine(renderer,r.x+r.w-(1+i),r.y+(r.h-32),r.x+r.w-(1+i),r.y+r.h);
|
||||||
|
}
|
||||||
|
SDL_SetRenderDrawColor(renderer,bottomMiddleColor.r,bottomMiddleColor.g,bottomMiddleColor.b,bottomMiddleColor.a);
|
||||||
|
for(int i = 0; i < win->palette.borderSize; i++)
|
||||||
|
{
|
||||||
|
SDL_RenderDrawLine(renderer,r.x,(r.y+(r.h-32))+i,r.x+r.w,(r.y+(r.h-32))+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SDL_SetRenderDrawColor(renderer,win->palette.accent.r,win->palette.accent.g,win->palette.accent.b,win->palette.accent.a);
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
int x1 = 15;
|
||||||
|
int y1 = 8 + i;
|
||||||
|
|
||||||
|
int x2 = 9;
|
||||||
|
int y2 = 18 + i;
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x1+r.x,y1+r.y,x2+r.x,y2+r.y);
|
||||||
|
|
||||||
|
int x3 = 31-x1;
|
||||||
|
int x4 = 31-x2;
|
||||||
|
SDL_RenderDrawLine(renderer,x3+r.x,y1+r.y,x4+r.x,y2+r.y);
|
||||||
|
|
||||||
|
int y3 = 31-y1;
|
||||||
|
int y4 = 31-y2;
|
||||||
|
|
||||||
|
SDL_RenderDrawLine(renderer,x1+r.x,y3+r.y+(r.h-32),x2+r.x,y4+r.y+(r.h-32));
|
||||||
|
SDL_RenderDrawLine(renderer,x3+r.x,y3+r.y+(r.h-32),x4+r.x,y4+r.y+(r.h-32));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t height = (uint64_t)r.h - 66;
|
||||||
|
uint64_t scrollSize = 4;
|
||||||
|
uint64_t dif = max-min;
|
||||||
|
if(dif > 0)
|
||||||
|
scrollSize = height / dif;
|
||||||
|
|
||||||
|
if(scrollSize < 4) scrollSize=4;
|
||||||
|
|
||||||
|
|
||||||
|
double scroll = 0;
|
||||||
|
if(dif > 0)
|
||||||
|
scroll = (double)(value-min) / (double)dif;
|
||||||
|
|
||||||
|
uint64_t scrollY = scroll * (height-scrollSize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(scrollY > height-scrollSize) scrollY = height-scrollSize;
|
||||||
|
SDL_Rect r2={.x=r.x+win->palette.borderSize,.y=(int)scrollY+r.y+32,.w = r.w-(win->palette.borderSize*2),.h=(int)scrollSize};
|
||||||
|
SDL_RenderFillRect(renderer,&r2);
|
||||||
|
}
|
||||||
|
bool VScrollView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
if(event.type == SDL_MOUSEMOTION)
|
||||||
|
{
|
||||||
|
bool inside = event.motion.x >= visibleBounds.x && event.motion.x < visibleBounds.x+visibleBounds.w && event.motion.y >= visibleBounds.y && event.motion.y < visibleBounds.y+visibleBounds.h;
|
||||||
|
bool hoverFlag = this->GetViewFlag(VIEWFLAG_HOVER_STATE) || this->GetViewFlag(VIEWFLAG_HOVER_B1STATE) || this->GetViewFlag(VIEWFLAG_HOVER_B2STATE);
|
||||||
|
if(inside && !hoverFlag)
|
||||||
|
{
|
||||||
|
int y = event.motion.y - myBounds.y;
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
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);
|
||||||
|
} else if(inside) {
|
||||||
|
int y = event.motion.y - myBounds.y;
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,true);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B1STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_B2STATE,false);
|
||||||
|
this->SetViewFlag(VIEWFLAG_HOVER_STATE,true);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||||
|
{
|
||||||
|
int y = event.motion.y - myBounds.y;
|
||||||
|
if(y <= 32)
|
||||||
|
{
|
||||||
|
value = min;
|
||||||
|
}
|
||||||
|
else if(y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
value=max;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint64_t height = (uint64_t)myBounds.h - 66;
|
||||||
|
uint64_t y2 = y-33;
|
||||||
|
|
||||||
|
double off = (double)y2 / (double)height;
|
||||||
|
|
||||||
|
value = round((max-min)*off)+min;
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(event.type == SDL_MOUSEBUTTONDOWN)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.y;
|
||||||
|
cea.which = event.button.which;
|
||||||
|
if(cea.y <= 32)
|
||||||
|
{
|
||||||
|
//up btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE,true);
|
||||||
|
}
|
||||||
|
else if(cea.y >= myBounds.h-32)
|
||||||
|
{
|
||||||
|
//down btn
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE,true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_STATE,true);
|
||||||
|
|
||||||
|
uint64_t height = (uint64_t)myBounds.h - 66;
|
||||||
|
uint64_t y2 = cea.y-33;
|
||||||
|
|
||||||
|
double off = (double)y2 / (double)height;
|
||||||
|
|
||||||
|
value = round((max-min)*off)+min;
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
}
|
||||||
|
OnMouseDown(cea);
|
||||||
|
this->MouseDown.Invoke(this,cea);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(event.type == SDL_MOUSEBUTTONUP)
|
||||||
|
{
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_STATE))
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.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,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE))
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.y;
|
||||||
|
cea.which = event.button.which;
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B1STATE,false);
|
||||||
|
OnMouseUp(cea);
|
||||||
|
this->MouseUp.Invoke(this,cea);
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
OnClick(cea2);
|
||||||
|
this->Click.Invoke(this,cea2);
|
||||||
|
this->value -= step;
|
||||||
|
if(this->value < min) this->value=min;
|
||||||
|
if(this->value >= max) this->value=min;
|
||||||
|
OnValueChanged(cea2);
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this->GetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE))
|
||||||
|
{
|
||||||
|
GUIMouseButtonEventArgs cea;
|
||||||
|
cea.button = (int)event.button.button;
|
||||||
|
cea.x = event.button.x - myBounds.x;
|
||||||
|
cea.y = event.button.y - myBounds.y;
|
||||||
|
cea.which = event.button.which;
|
||||||
|
this->SetViewFlag(VIEWFLAG_MOUSEDOWN_B2STATE,false);
|
||||||
|
OnMouseUp(cea);
|
||||||
|
this->MouseUp.Invoke(this,cea);
|
||||||
|
GUIEventArgs cea2;
|
||||||
|
OnClick(cea2);
|
||||||
|
this->Click.Invoke(this,cea2);
|
||||||
|
this->value += step;
|
||||||
|
if(this->value > max) this->value=max;
|
||||||
|
OnValueChanged(cea2);
|
||||||
|
this->ValueChanged.Invoke(this,cea2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return View::OnEvent(event,myBounds,visibleBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
270
src/SDL2/Views/VStackView.cpp
Normal file
270
src/SDL2/Views/VStackView.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
|
#include "TessesFramework/SDL2/Views/VStackView.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::SDL2::Views
|
||||||
|
{
|
||||||
|
void VStackView::OnDraw(SDL_Renderer* renderer, SDL_Rect& r)
|
||||||
|
{
|
||||||
|
int numberOfCells = 0;
|
||||||
|
int freeHeight = r.h;
|
||||||
|
std::vector<int> sizes;
|
||||||
|
sizes.resize(this->items.size());
|
||||||
|
|
||||||
|
freeHeight -= (this->items.size() - 1) * this->spacing;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first > 0)
|
||||||
|
{
|
||||||
|
//static size
|
||||||
|
sizes[i] = this->items[i].first;
|
||||||
|
freeHeight-= this->items[i].first;
|
||||||
|
}
|
||||||
|
else if(this->items[i].first == 0)
|
||||||
|
{
|
||||||
|
auto prefered = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(prefered.second > 0)
|
||||||
|
{
|
||||||
|
sizes[i] = prefered.second;
|
||||||
|
freeHeight -= prefered.second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sizes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numberOfCells -= this->items[i].first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cellSize = numberOfCells == 0 ? 0 : freeHeight / numberOfCells;
|
||||||
|
|
||||||
|
|
||||||
|
for(int i = 0; i < this->items.size();i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first < 0)
|
||||||
|
{
|
||||||
|
int myHeight =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
auto minSz = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(minSz.second > myHeight) {
|
||||||
|
sizes[i] = minSz.second;
|
||||||
|
freeHeight -= minSz.second;
|
||||||
|
numberOfCells -= -(this->items[i].first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cellSize = numberOfCells == 0 ? 0 : freeHeight / numberOfCells;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(i > 0) y += spacing;
|
||||||
|
|
||||||
|
if(sizes[i] == 0)
|
||||||
|
{
|
||||||
|
int myHeight =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x = 0,
|
||||||
|
.y=y,
|
||||||
|
.w=r.w,
|
||||||
|
.h=myHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
theirBounds.x += r.x;
|
||||||
|
theirBounds.y += r.y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnDraw(this->items[i].second.first,renderer, theirBounds);
|
||||||
|
y+=myHeight;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x = 0,
|
||||||
|
.y=y,
|
||||||
|
.w=r.w,
|
||||||
|
.h=sizes[i]
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
theirBounds.x += r.x;
|
||||||
|
theirBounds.y += r.y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnDraw(this->items[i].second.first,renderer, theirBounds);
|
||||||
|
y+=sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool VStackView::OnEvent(SDL_Event& event, SDL_Rect& myBounds, SDL_Rect& visibleBounds)
|
||||||
|
{
|
||||||
|
int numberOfCells = 0;
|
||||||
|
int freeHeight = myBounds.h;
|
||||||
|
std::vector<int> sizes;
|
||||||
|
sizes.resize(this->items.size());
|
||||||
|
|
||||||
|
|
||||||
|
freeHeight -= (this->items.size() - 1) * this->spacing;
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first > 0)
|
||||||
|
{
|
||||||
|
//static size
|
||||||
|
sizes[i] = this->items[i].first;
|
||||||
|
freeHeight-= this->items[i].first;
|
||||||
|
}
|
||||||
|
else if(this->items[i].first == 0)
|
||||||
|
{
|
||||||
|
auto prefered = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(prefered.second > 0)
|
||||||
|
{
|
||||||
|
sizes[i] = prefered.second;
|
||||||
|
freeHeight -= prefered.second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sizes[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numberOfCells -= this->items[i].first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int cellSize = numberOfCells == 0 ? 0 : freeHeight / numberOfCells;
|
||||||
|
|
||||||
|
for(int i = 0; i < this->items.size();i++)
|
||||||
|
{
|
||||||
|
if(this->items[i].first < 0)
|
||||||
|
{
|
||||||
|
int myHeight =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
auto minSz = this->items[i].second.first->PreferedMinSize();
|
||||||
|
if(minSz.second > myHeight) {
|
||||||
|
sizes[i] = minSz.second;
|
||||||
|
freeHeight -= minSz.second;
|
||||||
|
numberOfCells -= -(this->items[i].first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cellSize = numberOfCells == 0 ? 0 : freeHeight / numberOfCells;
|
||||||
|
int y = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for(size_t i = 0; i < this->items.size(); i++)
|
||||||
|
{
|
||||||
|
if(i > 0) y += spacing;
|
||||||
|
if(sizes[i] == 0)
|
||||||
|
{
|
||||||
|
int myHeight =((-(this->items[i].first)) * cellSize);
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x = 0,
|
||||||
|
.y=y,
|
||||||
|
.w=myBounds.w,
|
||||||
|
.h=myHeight
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_Rect theirVisibleBounds = theirBounds;
|
||||||
|
theirVisibleBounds.x += visibleBounds.x;
|
||||||
|
theirVisibleBounds.y += visibleBounds.y;
|
||||||
|
|
||||||
|
theirBounds.x += myBounds.x;
|
||||||
|
theirBounds.y += myBounds.y;
|
||||||
|
Clipper::ClipRect(theirVisibleBounds, visibleBounds);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnEvent(this->items[i].second.first,event,theirBounds,theirVisibleBounds);
|
||||||
|
|
||||||
|
y+=myHeight;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
SDL_Rect theirBounds = {
|
||||||
|
.x = 0,
|
||||||
|
.y=y,
|
||||||
|
.w=myBounds.w,
|
||||||
|
.h=sizes[i]
|
||||||
|
};
|
||||||
|
|
||||||
|
SDL_Rect theirVisibleBounds = theirBounds;
|
||||||
|
theirVisibleBounds.x += visibleBounds.x;
|
||||||
|
theirVisibleBounds.y += visibleBounds.y;
|
||||||
|
|
||||||
|
theirBounds.x += myBounds.x;
|
||||||
|
theirBounds.y += myBounds.y;
|
||||||
|
Clipper::ClipRect(theirVisibleBounds, visibleBounds);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CallOnEvent(this->items[i].second.first,event,theirBounds,theirVisibleBounds);
|
||||||
|
|
||||||
|
y+=sizes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
VStackView::VStackView() : ContainerView()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void VStackView::Add(int sz, View* view, bool owns)
|
||||||
|
{
|
||||||
|
this->items.push_back(std::pair<int,std::pair<View*,bool>>(sz,std::pair<View*,bool>(view,owns)));
|
||||||
|
this->AssignChildParentToThis(view);
|
||||||
|
}
|
||||||
|
void VStackView::Remove(View* view)
|
||||||
|
{
|
||||||
|
for(auto index = this->items.begin(); index < this->items.end(); index++)
|
||||||
|
{
|
||||||
|
if(index->second.first == view)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(index->second.first != nullptr && index->second.second)
|
||||||
|
delete view;
|
||||||
|
this->items.erase(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void VStackView::Clear()
|
||||||
|
{
|
||||||
|
for(auto& item : this->items)
|
||||||
|
if(item.second.second && item.second.first != nullptr) delete item.second.first;
|
||||||
|
items = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VStackView::ViewCount()
|
||||||
|
{
|
||||||
|
return this->items.size();
|
||||||
|
}
|
||||||
|
View* VStackView::GetViewAt(size_t index)
|
||||||
|
{
|
||||||
|
return this->items.at(index).second.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
VStackView::~VStackView()
|
||||||
|
{
|
||||||
|
for(auto& item : this->items)
|
||||||
|
if(item.second.second && item.second.first != nullptr) delete item.second.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -6,6 +6,7 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
|
|||||||
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
|
#if defined(TESSESFRAMEWORK_ENABLE_NETWORKING)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(GEKKO)
|
#if defined(GEKKO)
|
||||||
|
|
||||||
#define ss_family sin_family
|
#define ss_family sin_family
|
||||||
@ -24,9 +25,11 @@ using HttpUtils = Tesses::Framework::Http::HttpUtils;
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <afunix.h>
|
||||||
#undef min
|
#undef min
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
#else
|
#else
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
|||||||
@ -114,7 +114,7 @@ namespace Tesses::Framework::Streams {
|
|||||||
strm.Flush();
|
strm.Flush();
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
delete buffer;
|
delete[] buffer;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Stream::~Stream()
|
Stream::~Stream()
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -67,6 +68,25 @@ namespace Tesses::Framework
|
|||||||
volatile static bool isRunningSig=true;
|
volatile static bool isRunningSig=true;
|
||||||
volatile static std::atomic<bool> isRunning;
|
volatile static std::atomic<bool> isRunning;
|
||||||
volatile static std::atomic<bool> gaming_console_events=true;
|
volatile static std::atomic<bool> gaming_console_events=true;
|
||||||
|
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
Threading::Mutex invokings_mtx;
|
||||||
|
|
||||||
|
std::queue<std::function<void()>> invokings;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void TF_Invoke(std::function<void()> cb)
|
||||||
|
{
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
invokings_mtx.Lock();
|
||||||
|
invokings.push(cb);
|
||||||
|
invokings_mtx.Unlock();
|
||||||
|
#else
|
||||||
|
cb();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void TF_ConnectToSelf(uint16_t port)
|
void TF_ConnectToSelf(uint16_t port)
|
||||||
{
|
{
|
||||||
Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false);
|
Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false);
|
||||||
@ -103,8 +123,19 @@ namespace Tesses::Framework
|
|||||||
OnItteraton.Invoke(ittr++);
|
OnItteraton.Invoke(ittr++);
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
|
||||||
Tesses::Framework::Threading::LookForFinishedThreads();
|
Tesses::Framework::Threading::LookForFinishedThreads();
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
|
||||||
|
invokings_mtx.Lock();
|
||||||
|
auto invokes = invokings;
|
||||||
|
invokings_mtx.Unlock();
|
||||||
|
while(!invokes.empty())
|
||||||
|
{
|
||||||
|
invokes.front()();
|
||||||
|
invokes.pop();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!isRunningSig) isRunning=false;
|
if(!isRunningSig) isRunning=false;
|
||||||
#if defined(GEKKO)
|
#if defined(GEKKO)
|
||||||
@ -133,6 +164,14 @@ namespace Tesses::Framework
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
MSG winMSG;
|
||||||
|
if (PeekMessage(&winMSG, NULL, WM_QUIT, WM_QUIT, 1))
|
||||||
|
{
|
||||||
|
isRunning = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
Tesses::Framework::SDL2::gui.Update();
|
Tesses::Framework::SDL2::gui.Update();
|
||||||
#endif
|
#endif
|
||||||
@ -149,6 +188,8 @@ namespace Tesses::Framework
|
|||||||
#endif
|
#endif
|
||||||
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
#if defined(TESSESFRAMEWORK_ENABLE_SDL2)
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
Tesses::Framework::SDL2::gui.CloseWindows();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void TF_Init()
|
void TF_Init()
|
||||||
@ -182,6 +223,8 @@ namespace Tesses::Framework
|
|||||||
tzset();
|
tzset();
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
system(" ");
|
system(" ");
|
||||||
|
signal(SIGINT, _sigInt);
|
||||||
|
signal(SIGTERM, _sigInt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isRunning=true;
|
isRunning=true;
|
||||||
@ -214,6 +257,7 @@ if (iResult != 0) {
|
|||||||
#else
|
#else
|
||||||
signal(SIGPIPE,SIG_IGN);
|
signal(SIGPIPE,SIG_IGN);
|
||||||
signal(SIGINT,_sigInt);
|
signal(SIGINT,_sigInt);
|
||||||
|
signal(SIGTERM, _sigInt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
270
src/Text/StringConverter.cpp
Normal file
270
src/Text/StringConverter.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
#include "TessesFramework/Text/StringConverter.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::Framework::Text::StringConverter {
|
||||||
|
void UTF8::FromUTF16(std::basic_string<char>& utf8, const std::basic_string<char16_t>& utf16)
|
||||||
|
{
|
||||||
|
for (size_t i=0; i < utf16.size();i++)
|
||||||
|
{
|
||||||
|
char32_t c = utf16[i];
|
||||||
|
if ((c & 0xFC00) == 0xD800)
|
||||||
|
{
|
||||||
|
c = (c & 0x03FF) << 10;
|
||||||
|
i++;
|
||||||
|
if (i >= utf16.size()) return;
|
||||||
|
|
||||||
|
|
||||||
|
char32_t c2 = utf16[i];
|
||||||
|
if ((c2 & 0xFC00) != 0xDC00) continue;
|
||||||
|
|
||||||
|
|
||||||
|
c |= (c2 & 0x03FF);
|
||||||
|
|
||||||
|
c += 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c <= 0x7F)
|
||||||
|
{
|
||||||
|
utf8.push_back((char)c);
|
||||||
|
}
|
||||||
|
else if (c >= 0x80 && c <= 0x7FF)
|
||||||
|
{
|
||||||
|
uint8_t high = 0b11000000 | ((c >> 6) & 0b00011111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x800 && c <= 0xFFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11100000 | ((c >> 12) & 0b00001111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x010000 && c <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11110000 | ((c >> 18) & 0b00000111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 12) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t lowest = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
utf8.push_back((char)lowest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UTF8::FromUTF32(std::basic_string<char>& utf8, const std::basic_string<char32_t>& utf32)
|
||||||
|
{
|
||||||
|
for (auto c : utf32)
|
||||||
|
{
|
||||||
|
if (c <= 0x7F)
|
||||||
|
{
|
||||||
|
utf8.push_back((char)c);
|
||||||
|
}
|
||||||
|
else if (c >= 0x80 && c <= 0x7FF)
|
||||||
|
{
|
||||||
|
uint8_t high = 0b11000000 | ((c >> 6) & 0b00011111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x800 && c <= 0xFFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11100000 | ((c >> 12) & 0b00001111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
}
|
||||||
|
else if (c >= 0x010000 && c <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
uint8_t highest = 0b11110000 | ((c >> 18) & 0b00000111);
|
||||||
|
uint8_t high = 0b10000000 | ((c >> 12) & 0b00111111);
|
||||||
|
uint8_t low = 0b10000000 | ((c >> 6) & 0b00111111);
|
||||||
|
uint8_t lowest = 0b10000000 | (c & 0b00111111);
|
||||||
|
utf8.push_back((char)highest);
|
||||||
|
utf8.push_back((char)high);
|
||||||
|
utf8.push_back((char)low);
|
||||||
|
utf8.push_back((char)lowest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTF16::FromUTF8(std::basic_string<char16_t>& utf16, const std::basic_string<char>& utf8)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < utf8.size();i++)
|
||||||
|
{
|
||||||
|
uint8_t c = (uint8_t)utf8[i];
|
||||||
|
char32_t cres = 0;
|
||||||
|
if (c <= 127)
|
||||||
|
{
|
||||||
|
cres = (char32_t)c;
|
||||||
|
}
|
||||||
|
else if ((c & 0b11100000) == 0b11000000)
|
||||||
|
{
|
||||||
|
if (i + 1 < utf8.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c2 & 0b00111111;
|
||||||
|
cres |= (c & 0b00011111) << 6;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ((c & 0b11110000) == 0b11100000)
|
||||||
|
{
|
||||||
|
if (i + 2 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c3 & 0b00111111;
|
||||||
|
cres |= (c2 & 0b00111111) << 6;
|
||||||
|
cres |= (c & 0b00001111) << 12;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 2; continue; }
|
||||||
|
}
|
||||||
|
else if ((c & 0b11111000) == 0b11110000)
|
||||||
|
{
|
||||||
|
if (i + 3 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c4 = (uint8_t)utf8[++i];
|
||||||
|
|
||||||
|
cres |= c4 & 0b00111111;
|
||||||
|
cres |= (c3 & 0b00111111) << 6;
|
||||||
|
cres |= (c2 & 0b00111111) << 12;
|
||||||
|
cres |= (c & 0b00000111) << 18;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 3; continue; }
|
||||||
|
}
|
||||||
|
if (cres >= 0x10000 && cres <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
auto subtracted = cres - 0x10000;
|
||||||
|
|
||||||
|
auto high = (0x3FF & (subtracted >> 10)) | 0xD800;
|
||||||
|
auto low = (0x3FF & subtracted) | 0xDC00;
|
||||||
|
|
||||||
|
utf16.push_back(high);
|
||||||
|
utf16.push_back(low);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utf16.push_back((char16_t)cres);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void UTF16::FromUTF32(std::basic_string<char16_t>& utf16, const std::basic_string<char32_t>& utf32)
|
||||||
|
{
|
||||||
|
for (auto cres : utf32)
|
||||||
|
{
|
||||||
|
if (cres >= 0x10000 && cres <= 0x10FFFF)
|
||||||
|
{
|
||||||
|
auto subtracted = cres - 0x10000;
|
||||||
|
|
||||||
|
auto high = (0x3FF & (subtracted >> 10)) | 0xD800;
|
||||||
|
auto low = (0x3FF & subtracted) | 0xDC00;
|
||||||
|
|
||||||
|
utf16.push_back(high);
|
||||||
|
utf16.push_back(low);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
utf16.push_back((char16_t)cres);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTF32::FromUTF8(std::basic_string<char32_t>& utf32, const std::basic_string<char>& utf8)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < utf8.size();i++)
|
||||||
|
{
|
||||||
|
uint8_t c = (uint8_t)utf8[i];
|
||||||
|
char32_t cres = 0;
|
||||||
|
if (c <= 127)
|
||||||
|
{
|
||||||
|
cres=(char32_t)c;
|
||||||
|
}
|
||||||
|
else if ((c & 0b11100000) == 0b11000000)
|
||||||
|
{
|
||||||
|
if (i + 1 < utf8.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c2 & 0b00111111;
|
||||||
|
cres |= (c & 0b00011111) << 6;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if ((c & 0b11110000) == 0b11100000)
|
||||||
|
{
|
||||||
|
if (i + 2 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
cres |= c3 & 0b00111111;
|
||||||
|
cres |= (c2 & 0b00111111) << 6;
|
||||||
|
cres |= (c & 0b00001111) << 12;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 2; continue; }
|
||||||
|
}
|
||||||
|
else if ((c & 0b11111000) == 0b11110000)
|
||||||
|
{
|
||||||
|
if (i + 3 < utf8.size())
|
||||||
|
{
|
||||||
|
uint8_t c2 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c3 = (uint8_t)utf8[++i];
|
||||||
|
uint8_t c4 = (uint8_t)utf8[++i];
|
||||||
|
|
||||||
|
cres |= c4 & 0b00111111;
|
||||||
|
cres |= (c3 & 0b00111111) << 6;
|
||||||
|
cres |= (c2 & 0b00111111) << 12;
|
||||||
|
cres |= (c & 0b00000111) << 18;
|
||||||
|
|
||||||
|
}
|
||||||
|
else { i += 3; continue; }
|
||||||
|
}
|
||||||
|
utf32.push_back(cres);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void UTF32::FromUTF16(std::basic_string<char32_t>& utf32, const std::basic_string<char16_t>& utf16)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < utf16.size();i++)
|
||||||
|
{
|
||||||
|
char32_t c = utf16[i];
|
||||||
|
if ((c & 0xFC00) == 0xD800)
|
||||||
|
{
|
||||||
|
c = (c & 0x03FF) << 10;
|
||||||
|
i++;
|
||||||
|
if (i >= utf16.size()) return;
|
||||||
|
|
||||||
|
|
||||||
|
char32_t c2 = utf16[i];
|
||||||
|
if ((c2 & 0xFC00) != 0xDC00) continue;
|
||||||
|
|
||||||
|
|
||||||
|
c |= (c2 & 0x03FF);
|
||||||
|
|
||||||
|
c += 0x10000;
|
||||||
|
}
|
||||||
|
utf32.push_back(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user