Compare commits
19 Commits
font_from_
...
732e08736f
Author | SHA1 | Date | |
---|---|---|---|
732e08736f | |||
d5709c421c | |||
18c37f9934 | |||
53ae3f8ce5 | |||
b5e90528f0 | |||
22071b60e6 | |||
5283df7b98 | |||
21243ea979 | |||
1d212c5fab | |||
37239f1c25 | |||
780e1e06d4 | |||
7c227457cd | |||
5544adf345 | |||
6d3ef742b5 | |||
cba3282dce | |||
5c5e830f0f | |||
e08dbba940 | |||
752f2ebe2c | |||
a47d607a8d |
4
.github/workflows/cd.yml
vendored
4
.github/workflows/cd.yml
vendored
@ -153,7 +153,7 @@ jobs:
|
||||
git pull
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static pkgconf:x64-windows
|
||||
run: vcpkg install pkgconf:x64-windows libsodium:x64-windows-static pthreads:x64-windows-static opus:x64-windows-static libvpx:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
@ -212,7 +212,7 @@ jobs:
|
||||
git pull
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static pkgconf:x64-windows
|
||||
run: vcpkg install pkgconf:x64-windows libsodium:x64-windows-static pthreads:x64-windows-static opus:x64-windows-static libvpx:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -129,7 +129,7 @@ jobs:
|
||||
git pull
|
||||
|
||||
- name: Install Dependencies
|
||||
run: vcpkg install libsodium:x64-windows-static pthreads:x64-windows-static pkgconf:x64-windows
|
||||
run: vcpkg install pkgconf:x64-windows libsodium:x64-windows-static pthreads:x64-windows-static opus:x64-windows-static libvpx:x64-windows-static
|
||||
|
||||
# setup vs env
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
|
@ -1,109 +1,106 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Replace com.test.game with the identifier of your game below, e.g.
|
||||
com.gamemaker.game
|
||||
com.gamemaker.game
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.libsdl.app.tomato"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
android:installLocation="auto">
|
||||
|
||||
<!-- OpenGL ES 2.0 -->
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<!-- OpenGL ES 2.0 -->
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
|
||||
<!-- Touchscreen support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
<!-- Touchscreen support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Game controller support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.gamepad"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.usb.host"
|
||||
android:required="false" />
|
||||
<!-- Game controller support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.gamepad"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.usb.host"
|
||||
android:required="false" />
|
||||
|
||||
<!-- External mouse input events -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.type.pc"
|
||||
android:required="false" />
|
||||
<!-- External mouse input events -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.type.pc"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Audio recording support -->
|
||||
<!-- if you want to capture audio, uncomment this. -->
|
||||
<!-- <uses-feature
|
||||
android:name="android.hardware.microphone"
|
||||
android:required="false" /> -->
|
||||
<!-- Audio recording support -->
|
||||
<!-- if you want to capture audio, uncomment this. -->
|
||||
<!-- <uses-feature
|
||||
android:name="android.hardware.microphone"
|
||||
android:required="false" /> -->
|
||||
|
||||
<!-- Camera support -->
|
||||
<!-- if you want to record video, uncomment this. -->
|
||||
<!--
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
-->
|
||||
<!-- Camera support -->
|
||||
<!-- if you want to record video, uncomment this. -->
|
||||
<!--
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" />
|
||||
-->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- Allow downloading to the external storage on Android 5.1 and older -->
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="22" /> -->
|
||||
<!-- Allow downloading to the external storage on Android 5.1 and older -->
|
||||
<!-- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="22" /> -->
|
||||
|
||||
<!-- Allow access to Bluetooth devices -->
|
||||
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->
|
||||
<!-- <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> -->
|
||||
<!-- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> -->
|
||||
<!-- Allow access to Bluetooth devices -->
|
||||
<!-- Currently this is just for Steam Controller support and requires setting SDL_HINT_JOYSTICK_HIDAPI_STEAM -->
|
||||
<!-- <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> -->
|
||||
<!-- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> -->
|
||||
|
||||
<!-- Allow access to the vibrator -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<!-- Allow access to the vibrator -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<!-- if you want to capture audio, uncomment this. -->
|
||||
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
|
||||
<!-- if you want to capture audio, uncomment this. -->
|
||||
<!-- <uses-permission android:name="android.permission.RECORD_AUDIO" /> -->
|
||||
|
||||
<!-- Create a Java class extending SDLActivity and place it in a
|
||||
directory under app/src/main/java matching the package, e.g. app/src/main/java/com/gamemaker/game/MyGame.java
|
||||
<!-- Create a Java class extending SDLActivity and place it in a
|
||||
directory under app/src/main/java matching the package, e.g. app/src/main/java/com/gamemaker/game/MyGame.java
|
||||
|
||||
then replace "SDLActivity" with the name of your class (e.g. "MyGame")
|
||||
in the XML below.
|
||||
then replace "SDLActivity" with the name of your class (e.g. "MyGame")
|
||||
in the XML below.
|
||||
|
||||
An example Java class can be found in README-android.md
|
||||
-->
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
An example Java class can be found in README-android.md
|
||||
-->
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:appCategory="social"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:hardwareAccelerated="true" >
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:hardwareAccelerated="true" >
|
||||
|
||||
<!-- setting sdl hints. uses the string value -->
|
||||
<meta-data android:name="SDL_ENV.SDL_ANDROID_BLOCK_ON_PAUSE" android:value="0"/>
|
||||
|
||||
<activity android:name="TomatoActivity"
|
||||
android:label="@string/app_name"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||
android:preferMinimalPostProcessing="true"
|
||||
android:exported="true"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<!-- Let Android know that we can handle some USB devices and should receive this event -->
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
<!-- Drop file event -->
|
||||
<!--
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
-->
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
<activity android:name="TomatoActivity"
|
||||
android:label="@string/app_name"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleInstance"
|
||||
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||
android:preferMinimalPostProcessing="true"
|
||||
android:exported="true"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<!-- Let Android know that we can handle some USB devices and should receive this event -->
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
<!-- Drop file event -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
2
external/solanaceae_contact
vendored
2
external/solanaceae_contact
vendored
Submodule external/solanaceae_contact updated: e8b069c803...2401079c1d
2
external/solanaceae_object_store
vendored
2
external/solanaceae_object_store
vendored
Submodule external/solanaceae_object_store updated: be24b3815b...a93a89c5db
2
external/solanaceae_plugin
vendored
2
external/solanaceae_plugin
vendored
Submodule external/solanaceae_plugin updated: ade1b4ea74...54cd23433d
2
external/solanaceae_util
vendored
2
external/solanaceae_util
vendored
Submodule external/solanaceae_util updated: 4bda751f76...17d2baf736
17
external/toxcore/CMakeLists.txt
vendored
17
external/toxcore/CMakeLists.txt
vendored
@ -1,21 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.9...3.16 FATAL_ERROR)
|
||||
cmake_minimum_required(VERSION 3.13...3.16 FATAL_ERROR)
|
||||
|
||||
set(EXPERIMENTAL_API ON CACHE BOOL "" FORCE)
|
||||
set(UNITTEST OFF CACHE BOOL "" FORCE)
|
||||
set(BOOTSTRAP_DAEMON OFF CACHE BOOL "" FORCE)
|
||||
#set(BUILD_TOXAV ON CACHE BOOL "")
|
||||
|
||||
add_subdirectory(./c-toxcore)
|
||||
|
||||
# the ideal case
|
||||
#add_library(toxcore ALIAS toxcore_static)
|
||||
#message("II BUILD_TOXAV: ${BUILD_TOXAV}")
|
||||
|
||||
# the sad case
|
||||
add_library(toxcore INTERFACE)
|
||||
|
||||
if (TARGET toxcore_static)
|
||||
target_link_libraries(toxcore INTERFACE toxcore_static)
|
||||
|
||||
# the ideal case
|
||||
#add_library(toxcore ALIAS toxcore_static)
|
||||
else()
|
||||
target_link_libraries(toxcore INTERFACE toxcore_shared)
|
||||
|
||||
# the ideal case
|
||||
#add_library(toxcore ALIAS toxcore_shared)
|
||||
endif()
|
||||
|
||||
# HACK: "install" api headers into binary dir
|
||||
@ -64,3 +70,8 @@ elseif(sodium_FOUND)
|
||||
else()
|
||||
message(SEND_ERROR "missing libsodium")
|
||||
endif()
|
||||
|
||||
#if(BUILD_TOXAV)
|
||||
# set_target_properties(toxcore PROPERTIES TOX_HAS_TOXAV ON)
|
||||
#endif()
|
||||
|
||||
|
6
flake.lock
generated
6
flake.lock
generated
@ -20,11 +20,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1718111384,
|
||||
"narHash": "sha256-7tSst0S5FOmcgvNtfy6cjZX5w8CabCVAfAeCkhY4OVg=",
|
||||
"lastModified": 1720691131,
|
||||
"narHash": "sha256-CWT+KN8aTPyMIx8P303gsVxUnkinIz0a/Cmasz1jyIM=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a508a44af0c1b1b57785c34d8b54783536273eeb",
|
||||
"rev": "a046c1202e11b62cbede5385ba64908feb7bfac4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -75,11 +75,16 @@
|
||||
#(libsodium.override { stdenv = pkgs.pkgsStatic.stdenv; })
|
||||
#pkgsStatic.libsodium
|
||||
libsodium
|
||||
libopus
|
||||
libvpx
|
||||
] ++ self.packages.${system}.default.dlopenBuildInputs;
|
||||
|
||||
cmakeFlags = [
|
||||
"-DTOMATO_ASAN=OFF"
|
||||
"-DCMAKE_BUILD_TYPE=RelWithDebInfo"
|
||||
#"-DCMAKE_BUILD_TYPE=Debug"
|
||||
#"-DCMAKE_C_FLAGS:STRING=-Og"
|
||||
#"-DCMAKE_CXX_FLAGS:STRING=-Og"
|
||||
|
||||
"-DFETCHCONTENT_SOURCE_DIR_JSON=${nlohmann-json}" # we care about the version
|
||||
# TODO: use package instead
|
||||
|
@ -67,6 +67,16 @@ target_sources(tomato PUBLIC
|
||||
|
||||
./chat_gui/theme.hpp
|
||||
./chat_gui/theme.cpp
|
||||
./chat_gui/icons/direct.hpp
|
||||
./chat_gui/icons/direct.cpp
|
||||
./chat_gui/icons/cloud.hpp
|
||||
./chat_gui/icons/cloud.cpp
|
||||
./chat_gui/icons/mail.hpp
|
||||
./chat_gui/icons/mail.cpp
|
||||
./chat_gui/icons/person.hpp
|
||||
./chat_gui/icons/person.cpp
|
||||
./chat_gui/icons/group.hpp
|
||||
./chat_gui/icons/group.cpp
|
||||
./chat_gui/contact_list.hpp
|
||||
./chat_gui/contact_list.cpp
|
||||
./chat_gui/file_selector.hpp
|
||||
@ -76,6 +86,10 @@ target_sources(tomato PUBLIC
|
||||
./chat_gui/settings_window.hpp
|
||||
./chat_gui/settings_window.cpp
|
||||
|
||||
./imgui_entt_entity_editor.hpp
|
||||
./object_store_ui.hpp
|
||||
./object_store_ui.cpp
|
||||
|
||||
./tox_ui_utils.hpp
|
||||
./tox_ui_utils.cpp
|
||||
|
||||
|
@ -1,139 +1,16 @@
|
||||
#include "./contact_list.hpp"
|
||||
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
#include <solanaceae/util/utils.hpp>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
//#include <imgui/imgui_internal.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconDirectLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// arrow 1
|
||||
// (3,1) -> (9,7)
|
||||
PLINE(0.3f, 0.1f, 0.9f, 0.7f)
|
||||
// (9,7) -> (9,5)
|
||||
PLINE(0.9f, 0.7f, 0.9f, 0.5f)
|
||||
// (9,7) -> (7,7)
|
||||
PLINE(0.9f, 0.7f, 0.7f, 0.7f)
|
||||
|
||||
// arrow 2
|
||||
// (7,9) -> (1,3)
|
||||
PLINE(0.7f, 0.9f, 0.1f, 0.3f)
|
||||
// (1,3) -> (3,3)
|
||||
PLINE(0.1f, 0.3f, 0.3f, 0.3f)
|
||||
// (1,3) -> (1,5)
|
||||
PLINE(0.1f, 0.3f, 0.1f, 0.5f)
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
static void drawIconDirect(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconDirectLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconDirectLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
|
||||
static void drawIconCloud(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
std::array<ImVec2, 19> points {{
|
||||
{0.2f, 0.9f},
|
||||
{0.8f, 0.9f},
|
||||
{0.9f, 0.8f},
|
||||
{0.9f, 0.7f},
|
||||
{0.7f, 0.7f},
|
||||
{0.9f, 0.5f},
|
||||
{0.9f, 0.4f},
|
||||
{0.8f, 0.2f},
|
||||
{0.6f, 0.2f},
|
||||
{0.5f, 0.3f},
|
||||
{0.5f, 0.5f},
|
||||
{0.4f, 0.4f},
|
||||
{0.3f, 0.4f},
|
||||
{0.2f, 0.5f},
|
||||
{0.2f, 0.6f},
|
||||
{0.3f, 0.7f},
|
||||
{0.1f, 0.7f},
|
||||
{0.1f, 0.8f},
|
||||
{0.2f, 0.9f},
|
||||
}};
|
||||
for (auto& v : points) {
|
||||
v.y -= 0.1f;
|
||||
v = {p0.x + p1_o.x*v.x, p0.y + p1_o.y*v.y};
|
||||
}
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_back, ImDrawFlags_None, 4.f);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_main, ImDrawFlags_None, 1.5f);
|
||||
}
|
||||
|
||||
static void drawIconMailLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// quad
|
||||
// (1,2) -> (1,8)
|
||||
PLINE(0.1f, 0.2f, 0.1f, 0.8f)
|
||||
// (1,8) -> (9,8)
|
||||
PLINE(0.1f, 0.8f, 0.9f, 0.8f)
|
||||
// (9,8) -> (9,2)
|
||||
PLINE(0.9f, 0.8f, 0.9f, 0.2f)
|
||||
// (9,2) -> (1,2)
|
||||
PLINE(0.9f, 0.2f, 0.1f, 0.2f)
|
||||
|
||||
// lip
|
||||
// (1,2) -> (5,5)
|
||||
PLINE(0.1f, 0.2f, 0.5f, 0.5f)
|
||||
// (5,5) -> (9,2)
|
||||
PLINE(0.5f, 0.5f, 0.9f, 0.2f)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
static void drawIconMail(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconMailLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconMailLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
#include "./icons/direct.hpp"
|
||||
#include "./icons/cloud.hpp"
|
||||
#include "./icons/mail.hpp"
|
||||
#include "./icons/person.hpp"
|
||||
#include "./icons/group.hpp"
|
||||
|
||||
void renderAvatar(
|
||||
const Theme& th,
|
||||
@ -220,6 +97,11 @@ bool renderContactBig(
|
||||
|
||||
const auto* cstate = c.try_get<Contact::Components::ConnectionState>();
|
||||
if (ImGui::BeginItemTooltip()) {
|
||||
if (c.all_of<Contact::Components::ID>()) {
|
||||
const auto id_str = bin2hex(c.get<Contact::Components::ID>().data);
|
||||
ImGui::Text("ID: %s", id_str.c_str());
|
||||
}
|
||||
|
||||
if (cstate != nullptr) {
|
||||
ImGui::Text("Connection state: %s",
|
||||
(cstate->state == Contact::Components::ConnectionState::disconnected)
|
||||
@ -264,6 +146,9 @@ bool renderContactBig(
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
ImGui::BeginGroup();
|
||||
{
|
||||
const bool is_group = c.all_of<Contact::Components::TagGroup>();
|
||||
const bool is_private = c.all_of<Contact::Components::TagPrivate>();
|
||||
|
||||
{ // line 1
|
||||
if (line_height == 1 && cstate != nullptr) {
|
||||
// icon pos
|
||||
@ -271,23 +156,52 @@ bool renderContactBig(
|
||||
p0.y += ImGui::GetStyle().FramePadding.y;
|
||||
ImVec2 p1_o = {img_y, img_y}; // img_y is 1 line_height in this case
|
||||
|
||||
const ImU32 col_back = ImGui::GetColorU32(th.getColor<ThemeCol_Contact::icon_backdrop>());
|
||||
if (cstate->state == Contact::Components::ConnectionState::direct) { // direct icon
|
||||
drawIconDirect(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_direct>()),
|
||||
col_back
|
||||
);
|
||||
} else if (cstate->state == Contact::Components::ConnectionState::cloud) { // cloud icon
|
||||
drawIconCloud(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_cloud>()),
|
||||
col_back
|
||||
);
|
||||
}
|
||||
ImGui::Dummy(p1_o);
|
||||
if (ImGui::IsItemVisible()) {
|
||||
const ImU32 col_back = ImGui::GetColorU32(th.getColor<ThemeCol_Contact::icon_backdrop>());
|
||||
if (cstate->state == Contact::Components::ConnectionState::direct) { // direct icon
|
||||
drawIconDirect(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_direct>()),
|
||||
col_back
|
||||
);
|
||||
} else if (cstate->state == Contact::Components::ConnectionState::cloud) { // cloud icon
|
||||
drawIconCloud(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_cloud>()),
|
||||
col_back
|
||||
);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
}
|
||||
|
||||
// we dont render group/private in 1lh mode
|
||||
if (line_height != 1 && (is_private || is_group)) {
|
||||
// icon pos
|
||||
auto p0 = ImGui::GetCursorScreenPos();
|
||||
p0.y += ImGui::GetStyle().FramePadding.y;
|
||||
const float box_hight = TEXT_BASE_HEIGHT - ImGui::GetStyle().FramePadding.y*2;
|
||||
ImVec2 p1_o = {box_hight, box_hight};
|
||||
|
||||
ImGui::Dummy(p1_o);
|
||||
if (ImGui::IsItemVisible()) {
|
||||
if (is_private) {
|
||||
drawIconPerson(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text))
|
||||
);
|
||||
} else if (is_group) {
|
||||
drawIconGroup(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(ImGui::GetStyleColorVec4(ImGuiCol_Text))
|
||||
);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
}
|
||||
|
||||
@ -327,23 +241,25 @@ bool renderContactBig(
|
||||
const float box_hight = TEXT_BASE_HEIGHT - ImGui::GetStyle().FramePadding.y*2;
|
||||
ImVec2 p1_o = {box_hight, box_hight};
|
||||
|
||||
const ImU32 col_back = ImGui::GetColorU32(th.getColor<ThemeCol_Contact::icon_backdrop>());
|
||||
if (cstate->state == Contact::Components::ConnectionState::direct) { // direct icon
|
||||
drawIconDirect(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_direct>()),
|
||||
col_back
|
||||
);
|
||||
} else if (cstate->state == Contact::Components::ConnectionState::cloud) { // cloud icon
|
||||
drawIconCloud(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_cloud>()),
|
||||
col_back
|
||||
);
|
||||
}
|
||||
ImGui::Dummy(p1_o);
|
||||
if (ImGui::IsItemVisible()) {
|
||||
const ImU32 col_back = ImGui::GetColorU32(th.getColor<ThemeCol_Contact::icon_backdrop>());
|
||||
if (cstate->state == Contact::Components::ConnectionState::direct) { // direct icon
|
||||
drawIconDirect(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_direct>()),
|
||||
col_back
|
||||
);
|
||||
} else if (cstate->state == Contact::Components::ConnectionState::cloud) { // cloud icon
|
||||
drawIconCloud(
|
||||
p0,
|
||||
p1_o,
|
||||
ImGui::GetColorU32(th.getColor<ThemeCol_Contact::avatar_online_cloud>()),
|
||||
col_back
|
||||
);
|
||||
}
|
||||
}
|
||||
ImGui::SameLine(0.f, same_line_spacing);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
void FileSelector::reset(void) {
|
||||
_is_valid = [](auto){ return true; };
|
||||
|
41
src/chat_gui/icons/cloud.cpp
Normal file
41
src/chat_gui/icons/cloud.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "./cloud.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
void drawIconCloud(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
std::array<ImVec2, 19> points {{
|
||||
{0.2f, 0.9f},
|
||||
{0.8f, 0.9f},
|
||||
{0.9f, 0.8f},
|
||||
{0.9f, 0.7f},
|
||||
{0.7f, 0.7f},
|
||||
{0.9f, 0.5f},
|
||||
{0.9f, 0.4f},
|
||||
{0.8f, 0.2f},
|
||||
{0.6f, 0.2f},
|
||||
{0.5f, 0.3f},
|
||||
{0.5f, 0.5f},
|
||||
{0.4f, 0.4f},
|
||||
{0.3f, 0.4f},
|
||||
{0.2f, 0.5f},
|
||||
{0.2f, 0.6f},
|
||||
{0.3f, 0.7f},
|
||||
{0.1f, 0.7f},
|
||||
{0.1f, 0.8f},
|
||||
{0.2f, 0.9f},
|
||||
}};
|
||||
for (auto& v : points) {
|
||||
v.y -= 0.1f;
|
||||
v = {p0.x + p1_o.x*v.x, p0.y + p1_o.y*v.y};
|
||||
}
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_back, ImDrawFlags_None, 4.f);
|
||||
ImGui::GetWindowDrawList()->AddPolyline(points.data(), points.size(), col_main, ImDrawFlags_None, 1.5f);
|
||||
}
|
||||
|
11
src/chat_gui/icons/cloud.hpp
Normal file
11
src/chat_gui/icons/cloud.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconCloud(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
);
|
||||
|
49
src/chat_gui/icons/direct.cpp
Normal file
49
src/chat_gui/icons/direct.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "./direct.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconDirectLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// arrow 1
|
||||
// (3,1) -> (9,7)
|
||||
PLINE(0.3f, 0.1f, 0.9f, 0.7f)
|
||||
// (9,7) -> (9,5)
|
||||
PLINE(0.9f, 0.7f, 0.9f, 0.5f)
|
||||
// (9,7) -> (7,7)
|
||||
PLINE(0.9f, 0.7f, 0.7f, 0.7f)
|
||||
|
||||
// arrow 2
|
||||
// (7,9) -> (1,3)
|
||||
PLINE(0.7f, 0.9f, 0.1f, 0.3f)
|
||||
// (1,3) -> (3,3)
|
||||
PLINE(0.1f, 0.3f, 0.3f, 0.3f)
|
||||
// (1,3) -> (1,5)
|
||||
PLINE(0.1f, 0.3f, 0.1f, 0.5f)
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconDirect(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconDirectLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconDirectLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
|
10
src/chat_gui/icons/direct.hpp
Normal file
10
src/chat_gui/icons/direct.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconDirect(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
);
|
139
src/chat_gui/icons/group.cpp
Normal file
139
src/chat_gui/icons/group.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
#include "./group.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconGroupLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// person front
|
||||
// x y
|
||||
PLINE(
|
||||
0.1f, 0.9f,
|
||||
0.6f, 0.9f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.9f,
|
||||
0.6f, 0.7f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.7f,
|
||||
0.5f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.6f,
|
||||
0.4f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.6f,
|
||||
0.5f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.5f,
|
||||
0.5f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.4f,
|
||||
0.4f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.3f,
|
||||
0.3f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.3f,
|
||||
0.2f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.4f,
|
||||
0.2f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.5f,
|
||||
0.3f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.6f,
|
||||
0.2f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.6f,
|
||||
0.1f, 0.7f
|
||||
)
|
||||
PLINE(
|
||||
0.1f, 0.7f,
|
||||
0.1f, 0.9f
|
||||
)
|
||||
|
||||
// person back
|
||||
// x y
|
||||
PLINE(
|
||||
0.7f, 0.7f,
|
||||
0.9f, 0.7f
|
||||
)
|
||||
PLINE(
|
||||
0.9f, 0.7f,
|
||||
0.9f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.9f, 0.5f,
|
||||
0.8f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.4f,
|
||||
0.7f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.4f,
|
||||
0.8f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.3f,
|
||||
0.8f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.2f,
|
||||
0.7f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.1f,
|
||||
0.6f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.1f,
|
||||
0.5f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.2f,
|
||||
0.5f, 0.3f
|
||||
)
|
||||
PLINE(
|
||||
0.5f, 0.3f,
|
||||
0.6f, 0.4f
|
||||
)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconGroup(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
//drawIconGroupLines(p0, p1_o, col_back, 3.5f);
|
||||
drawIconGroupLines(p0, p1_o, col_main, 1.0f);
|
||||
}
|
||||
|
10
src/chat_gui/icons/group.hpp
Normal file
10
src/chat_gui/icons/group.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconGroup(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
);
|
||||
|
50
src/chat_gui/icons/mail.cpp
Normal file
50
src/chat_gui/icons/mail.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include "./mail.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconMailLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
// quad
|
||||
// (1,2) -> (1,8)
|
||||
PLINE(0.1f, 0.2f, 0.1f, 0.8f)
|
||||
// (1,8) -> (9,8)
|
||||
PLINE(0.1f, 0.8f, 0.9f, 0.8f)
|
||||
// (9,8) -> (9,2)
|
||||
PLINE(0.9f, 0.8f, 0.9f, 0.2f)
|
||||
// (9,2) -> (1,2)
|
||||
PLINE(0.9f, 0.2f, 0.1f, 0.2f)
|
||||
|
||||
// lip
|
||||
// (1,2) -> (5,5)
|
||||
PLINE(0.1f, 0.2f, 0.5f, 0.5f)
|
||||
// (5,5) -> (9,2)
|
||||
PLINE(0.5f, 0.5f, 0.9f, 0.2f)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconMail(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
drawIconMailLines(p0, p1_o, col_back, 4.0f);
|
||||
drawIconMailLines(p0, p1_o, col_main, 1.5f);
|
||||
}
|
||||
|
11
src/chat_gui/icons/mail.hpp
Normal file
11
src/chat_gui/icons/mail.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconMail(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main,
|
||||
const ImU32 col_back
|
||||
);
|
||||
|
101
src/chat_gui/icons/person.cpp
Normal file
101
src/chat_gui/icons/person.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "./person.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
static void drawIconPersonLines(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col,
|
||||
const float thickness
|
||||
) {
|
||||
#define PLINE(x0, y0, x1, y1) \
|
||||
ImGui::GetWindowDrawList()->AddLine( \
|
||||
{p0.x + p1_o.x*(x0), p0.y + p1_o.y*(y0)}, \
|
||||
{p0.x + p1_o.x*(x1), p0.y + p1_o.y*(y1)}, \
|
||||
col, \
|
||||
thickness \
|
||||
);
|
||||
|
||||
//// quad
|
||||
//// (1,2) -> (1,8)
|
||||
//PLINE(0.1f, 0.2f, 0.1f, 0.8f)
|
||||
//// (1,8) -> (9,8)
|
||||
//PLINE(0.1f, 0.8f, 0.9f, 0.8f)
|
||||
//// (9,8) -> (9,2)
|
||||
//PLINE(0.9f, 0.8f, 0.9f, 0.2f)
|
||||
//// (9,2) -> (1,2)
|
||||
//PLINE(0.9f, 0.2f, 0.1f, 0.2f)
|
||||
|
||||
// x y
|
||||
PLINE(
|
||||
0.2f, 0.8f,
|
||||
0.8f, 0.8f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.8f,
|
||||
0.8f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.8f, 0.6f,
|
||||
0.7f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.5f,
|
||||
0.6f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.5f,
|
||||
0.7f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.4f,
|
||||
0.7f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.7f, 0.2f,
|
||||
0.6f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.6f, 0.1f,
|
||||
0.4f, 0.1f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.1f,
|
||||
0.3f, 0.2f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.2f,
|
||||
0.3f, 0.4f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.4f,
|
||||
0.4f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.4f, 0.5f,
|
||||
0.3f, 0.5f
|
||||
)
|
||||
PLINE(
|
||||
0.3f, 0.5f,
|
||||
0.2f, 0.6f
|
||||
)
|
||||
PLINE(
|
||||
0.2f, 0.6f,
|
||||
0.2f, 0.8f
|
||||
)
|
||||
|
||||
#undef PLINE
|
||||
}
|
||||
|
||||
void drawIconPerson(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
) {
|
||||
// dark background
|
||||
// the circle looks bad in light mode
|
||||
//ImGui::GetWindowDrawList()->AddCircleFilled({p0.x + p1_o.x*0.5f, p0.y + p1_o.y*0.5f}, p1_o.x*0.5f, col_back);
|
||||
//drawIconPersonLines(p0, p1_o, col_back, 3.5f);
|
||||
drawIconPersonLines(p0, p1_o, col_main, 1.0f);
|
||||
}
|
||||
|
10
src/chat_gui/icons/person.hpp
Normal file
10
src/chat_gui/icons/person.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
void drawIconPerson(
|
||||
const ImVec2 p0,
|
||||
const ImVec2 p1_o,
|
||||
const ImU32 col_main
|
||||
);
|
||||
|
@ -63,6 +63,28 @@ static constexpr float lerp(float a, float b, float t) {
|
||||
return a + t * (b - a);
|
||||
}
|
||||
|
||||
// returns divider and places static suffix string into suffix_out
|
||||
static int64_t sizeToHumanReadable(int64_t file_size, const char*& suffix_out) {
|
||||
static const char* suffix_arr[] {
|
||||
"bytes",
|
||||
"KiB",
|
||||
"MiB",
|
||||
"GiB",
|
||||
"TiB",
|
||||
"PiB",
|
||||
// TODO: fix upper bound behaviour
|
||||
};
|
||||
int64_t divider = 1024;
|
||||
for (size_t ij = 0; ij < std::size(suffix_arr); ij++, divider *= 1024) {
|
||||
if (file_size < divider) {
|
||||
suffix_out = suffix_arr[ij];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (divider > 1024) ? (divider / 1024) : 1;
|
||||
}
|
||||
|
||||
static std::string file_path_url_escape(const std::string&& value) {
|
||||
std::ostringstream escaped;
|
||||
|
||||
@ -817,6 +839,7 @@ void ChatGui4::sendFilePath(const char* file_path) {
|
||||
void ChatGui4::renderMessageBodyText(Message3Registry& reg, const Message3 e) {
|
||||
const auto& msgtext = reg.get<Message::Components::MessageText>(e).text;
|
||||
|
||||
#if 0
|
||||
// TODO: set word wrap
|
||||
ImVec2 text_size = ImGui::CalcTextSize(msgtext.c_str(), msgtext.c_str()+msgtext.size());
|
||||
text_size.x = -FLT_MIN; // fill width (suppresses label)
|
||||
@ -849,11 +872,72 @@ void ChatGui4::renderMessageBodyText(Message3Registry& reg, const Message3 e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("copy")) {
|
||||
ImGui::SetClipboardText(msgtext.c_str());
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
#else
|
||||
|
||||
ImGui::PushTextWrapPos(0.0f);
|
||||
std::string_view msgtext_sv{msgtext};
|
||||
size_t pos_prev {0};
|
||||
size_t pos_next {msgtext_sv.find_first_of('\n')};
|
||||
ImGui::BeginGroup();
|
||||
do {
|
||||
const auto current_line = msgtext_sv.substr(pos_prev, pos_next - pos_prev);
|
||||
if (current_line.front() == '>') {
|
||||
// TODO: theming
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, {0.3f, 0.9f, 0.1f, 1.f});
|
||||
ImGui::TextUnformatted(current_line.data(), current_line.data()+current_line.size());
|
||||
ImGui::PopStyleColor();
|
||||
} else {
|
||||
ImGui::TextUnformatted(current_line.data(), current_line.data()+current_line.size());
|
||||
}
|
||||
|
||||
if (pos_next != msgtext_sv.npos) {
|
||||
pos_next += 1; // skip past
|
||||
if (pos_next < msgtext_sv.size()) {
|
||||
pos_prev = pos_next; // old end is new start
|
||||
pos_next = msgtext_sv.find_first_of('\n', pos_next);
|
||||
} else {
|
||||
pos_prev = msgtext_sv.npos;
|
||||
pos_next = msgtext_sv.npos;
|
||||
}
|
||||
} else {
|
||||
pos_prev = msgtext_sv.npos;
|
||||
}
|
||||
} while (pos_prev != msgtext_sv.npos);
|
||||
|
||||
ImGui::EndGroup();
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
if (ImGui::BeginPopupContextItem("##text")) {
|
||||
if (ImGui::MenuItem("quote")) {
|
||||
//text_buffer.insert(0, (_cr.all_of<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name : "<unk>") + ": ");
|
||||
if (!_text_input_buffer.empty()) {
|
||||
_text_input_buffer += "\n";
|
||||
}
|
||||
|
||||
_text_input_buffer += "> ";
|
||||
|
||||
for (const char c : msgtext) {
|
||||
_text_input_buffer += c;
|
||||
|
||||
if (c == '\n') {
|
||||
_text_input_buffer += "> ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("copy")) {
|
||||
ImGui::SetClipboardText(msgtext.c_str());
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
||||
@ -995,8 +1079,16 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
||||
for (size_t i = 0; i < file_list.size(); i++) {
|
||||
ImGui::PushID(i);
|
||||
|
||||
const char* byte_suffix = "???";
|
||||
int64_t byte_divider = sizeToHumanReadable(file_list[i].file_size, byte_suffix);
|
||||
|
||||
// TODO: selectable text widget ?
|
||||
ImGui::Bullet(); ImGui::Text("%s (%lu)", file_list[i].file_name.c_str(), file_list[i].file_size);
|
||||
ImGui::Bullet(); ImGui::Text("%s (%.2lf %s)", file_list[i].file_name.c_str(), double(file_list[i].file_size)/byte_divider, byte_suffix);
|
||||
if (ImGui::BeginItemTooltip()) {
|
||||
ImGui::Text("TODO: file path?");
|
||||
ImGui::Text("%lu bytes", file_list[i].file_size);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (reg.all_of<Message::Components::Transfer::FileInfoLocal>(e)) {
|
||||
const auto& local_info = reg.get<Message::Components::Transfer::FileInfoLocal>(e);
|
||||
|
@ -27,6 +27,8 @@ struct ImageLoaderI {
|
||||
|
||||
// only positive values are valid
|
||||
ImageResult crop(int32_t c_x, int32_t c_y, int32_t c_w, int32_t c_h) const;
|
||||
|
||||
// TODO: scale
|
||||
};
|
||||
virtual ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) = 0;
|
||||
};
|
||||
|
319
src/imgui_entt_entity_editor.hpp
Normal file
319
src/imgui_entt_entity_editor.hpp
Normal file
@ -0,0 +1,319 @@
|
||||
// for the license, see the end of the file
|
||||
#pragma once
|
||||
|
||||
#include "entt/entity/fwd.hpp"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
#include <imgui.h>
|
||||
|
||||
#ifndef MM_IEEE_ASSERT
|
||||
#define MM_IEEE_ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
||||
#define MM_IEEE_IMGUI_PAYLOAD_TYPE_ENTITY "MM_IEEE_ENTITY"
|
||||
|
||||
#ifndef MM_IEEE_ENTITY_WIDGET
|
||||
#define MM_IEEE_ENTITY_WIDGET ::MM::EntityWidget
|
||||
#endif
|
||||
|
||||
namespace MM {
|
||||
|
||||
template <class EntityType>
|
||||
inline void EntityWidget(EntityType& e, entt::basic_registry<EntityType>& reg, bool dropTarget = false)
|
||||
{
|
||||
ImGui::PushID(static_cast<int>(entt::to_integral(e)));
|
||||
|
||||
if (reg.valid(e)) {
|
||||
ImGui::Text("ID: %d", entt::to_integral(e));
|
||||
} else {
|
||||
ImGui::Text("Invalid Entity");
|
||||
}
|
||||
|
||||
if (reg.valid(e)) {
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceAllowNullID)) {
|
||||
ImGui::SetDragDropPayload(MM_IEEE_IMGUI_PAYLOAD_TYPE_ENTITY, &e, sizeof(e));
|
||||
ImGui::Text("ID: %d", entt::to_integral(e));
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
|
||||
if (dropTarget && ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(MM_IEEE_IMGUI_PAYLOAD_TYPE_ENTITY)) {
|
||||
e = *(EntityType*)payload->Data;
|
||||
}
|
||||
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
template <class Component, class EntityType>
|
||||
void ComponentEditorWidget([[maybe_unused]] entt::basic_registry<EntityType>& registry, [[maybe_unused]] EntityType entity) {}
|
||||
|
||||
template <class Component, class EntityType>
|
||||
void ComponentAddAction(entt::basic_registry<EntityType>& registry, EntityType entity)
|
||||
{
|
||||
registry.template emplace<Component>(entity);
|
||||
}
|
||||
|
||||
template <class Component, class EntityType>
|
||||
void ComponentRemoveAction(entt::basic_registry<EntityType>& registry, EntityType entity)
|
||||
{
|
||||
registry.template remove<Component>(entity);
|
||||
}
|
||||
|
||||
template <class EntityType>
|
||||
class EntityEditor {
|
||||
public:
|
||||
using Registry = entt::basic_registry<EntityType>;
|
||||
using ComponentTypeID = entt::id_type;
|
||||
|
||||
struct ComponentInfo {
|
||||
using Callback = std::function<void(Registry&, EntityType)>;
|
||||
std::string name;
|
||||
Callback widget, create, destroy;
|
||||
};
|
||||
|
||||
bool show_window = true;
|
||||
|
||||
private:
|
||||
std::map<ComponentTypeID, ComponentInfo> component_infos;
|
||||
|
||||
bool entityHasComponent(Registry& registry, EntityType& entity, ComponentTypeID type_id)
|
||||
{
|
||||
const auto* storage_ptr = registry.storage(type_id);
|
||||
return storage_ptr != nullptr && storage_ptr->contains(entity);
|
||||
}
|
||||
|
||||
public:
|
||||
template <class Component>
|
||||
ComponentInfo& registerComponent(const ComponentInfo& component_info)
|
||||
{
|
||||
auto index = entt::type_hash<Component>::value();
|
||||
auto insert_info = component_infos.insert_or_assign(index, component_info);
|
||||
MM_IEEE_ASSERT(insert_info.second);
|
||||
return std::get<ComponentInfo>(*insert_info.first);
|
||||
}
|
||||
|
||||
template <class Component>
|
||||
ComponentInfo& registerComponent(const std::string& name, typename ComponentInfo::Callback widget)
|
||||
{
|
||||
return registerComponent<Component>(ComponentInfo{
|
||||
name,
|
||||
widget,
|
||||
ComponentAddAction<Component, EntityType>,
|
||||
ComponentRemoveAction<Component, EntityType>,
|
||||
});
|
||||
}
|
||||
|
||||
template <class Component>
|
||||
ComponentInfo& registerComponent(const std::string& name)
|
||||
{
|
||||
return registerComponent<Component>(name, ComponentEditorWidget<Component, EntityType>);
|
||||
}
|
||||
|
||||
void renderEditor(Registry& registry, EntityType& e)
|
||||
{
|
||||
ImGui::TextUnformatted("Editing:");
|
||||
ImGui::SameLine();
|
||||
|
||||
MM_IEEE_ENTITY_WIDGET(e, registry, true);
|
||||
|
||||
if (ImGui::Button("New")) {
|
||||
e = registry.create();
|
||||
}
|
||||
if (registry.valid(e)) {
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Clone")) {
|
||||
auto old_e = e;
|
||||
e = registry.create();
|
||||
|
||||
// create a copy of an entity component by component
|
||||
for (auto &&curr: registry.storage()) {
|
||||
if (auto &storage = curr.second; storage.contains(old_e)) {
|
||||
// TODO: do something with the return value. returns false on failure.
|
||||
storage.push(e, storage.value(old_e));
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::Dummy({10, 0}); // space destroy a bit, to not accidentally click it
|
||||
ImGui::SameLine();
|
||||
|
||||
// red button
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.65f, 0.15f, 0.15f, 1.f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.8f, 0.3f, 0.3f, 1.f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(1.f, 0.2f, 0.2f, 1.f));
|
||||
if (ImGui::Button("Destroy")) {
|
||||
registry.destroy(e);
|
||||
e = entt::null;
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (registry.valid(e)) {
|
||||
ImGui::PushID(static_cast<int>(entt::to_integral(e)));
|
||||
std::map<ComponentTypeID, ComponentInfo> has_not;
|
||||
for (auto& [component_type_id, ci] : component_infos) {
|
||||
if (entityHasComponent(registry, e, component_type_id)) {
|
||||
ImGui::PushID(component_type_id);
|
||||
if (ImGui::Button("-")) {
|
||||
ci.destroy(registry, e);
|
||||
ImGui::PopID();
|
||||
continue; // early out to prevent access to deleted data
|
||||
} else {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader(ci.name.c_str())) {
|
||||
ImGui::Indent(30.f);
|
||||
ImGui::PushID("Widget");
|
||||
ci.widget(registry, e);
|
||||
ImGui::PopID();
|
||||
ImGui::Unindent(30.f);
|
||||
}
|
||||
ImGui::PopID();
|
||||
} else {
|
||||
has_not[component_type_id] = ci;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_not.empty()) {
|
||||
if (ImGui::Button("+ Add Component")) {
|
||||
ImGui::OpenPopup("Add Component");
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopup("Add Component")) {
|
||||
ImGui::TextUnformatted("Available:");
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto& [component_type_id, ci] : has_not) {
|
||||
ImGui::PushID(component_type_id);
|
||||
if (ImGui::Selectable(ci.name.c_str())) {
|
||||
ci.create(registry, e);
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void renderEntityList(Registry& registry, std::set<ComponentTypeID>& comp_list)
|
||||
{
|
||||
ImGui::Text("Components Filter:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::SmallButton("clear")) {
|
||||
comp_list.clear();
|
||||
}
|
||||
|
||||
ImGui::Indent();
|
||||
|
||||
for (const auto& [component_type_id, ci] : component_infos) {
|
||||
bool is_in_list = comp_list.count(component_type_id);
|
||||
bool active = is_in_list;
|
||||
|
||||
ImGui::Checkbox(ci.name.c_str(), &active);
|
||||
|
||||
if (is_in_list && !active) { // remove
|
||||
comp_list.erase(component_type_id);
|
||||
} else if (!is_in_list && active) { // add
|
||||
comp_list.emplace(component_type_id);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Unindent();
|
||||
ImGui::Separator();
|
||||
|
||||
if (comp_list.empty()) {
|
||||
ImGui::Text("Orphans:");
|
||||
for (EntityType e : registry.template storage<EntityType>()) {
|
||||
if (registry.orphan(e)) {
|
||||
MM_IEEE_ENTITY_WIDGET(e, registry, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
entt::basic_runtime_view<entt::basic_sparse_set<EntityType>> view{};
|
||||
for (const auto type : comp_list) {
|
||||
auto* storage_ptr = registry.storage(type);
|
||||
if (storage_ptr != nullptr) {
|
||||
view.iterate(*storage_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add support for exclude
|
||||
|
||||
ImGui::Text("%lu Entities Matching:", view.size_hint());
|
||||
|
||||
if (ImGui::BeginChild("entity list")) {
|
||||
for (auto e : view) {
|
||||
MM_IEEE_ENTITY_WIDGET(e, registry, false);
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
|
||||
// displays both, editor and list
|
||||
// uses static internally, use only as a quick way to get going!
|
||||
void renderSimpleCombo(Registry& registry, EntityType& e)
|
||||
{
|
||||
if (show_window) {
|
||||
ImGui::SetNextWindowSize(ImVec2(550, 400), ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("Entity Editor", &show_window)) {
|
||||
if (ImGui::BeginChild("list", {200, 0}, true)) {
|
||||
static std::set<ComponentTypeID> comp_list;
|
||||
renderEntityList(registry, comp_list);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::BeginChild("editor")) {
|
||||
renderEditor(registry, e);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // MM
|
||||
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2022 Erik Scholz
|
||||
// Copyright (c) 2020 Gnik Droy
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
@ -51,7 +51,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
// more RAII
|
||||
std::unique_ptr<SDL_Window, decltype(&SDL_DestroyWindow)> window {
|
||||
SDL_CreateWindow("tomato", 1280, 720, SDL_WINDOW_RESIZABLE),
|
||||
SDL_CreateWindow("tomato", 1280, 720, SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY),
|
||||
&SDL_DestroyWindow
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,7 @@ MainScreen::MainScreen(SimpleConfigModel&& conf_, SDL_Renderer* renderer_, Theme
|
||||
msg_tc(mil, sdlrtu),
|
||||
cg(conf, rmm, cr, sdlrtu, contact_tc, msg_tc, theme),
|
||||
sw(conf),
|
||||
osui(os),
|
||||
tuiu(tc, conf),
|
||||
tdch(tpi)
|
||||
{
|
||||
@ -248,6 +249,7 @@ Screen* MainScreen::render(float time_delta, bool&) {
|
||||
|
||||
const float cg_interval = cg.render(time_delta); // render
|
||||
sw.render(); // render
|
||||
osui.render();
|
||||
tuiu.render(); // render
|
||||
tdch.render(); // render
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "./chat_gui4.hpp"
|
||||
#include "./chat_gui/settings_window.hpp"
|
||||
#include "./object_store_ui.hpp"
|
||||
#include "./tox_ui_utils.hpp"
|
||||
#include "./tox_dht_cap_histo.hpp"
|
||||
#include "./tox_friend_faux_offline_messaging.hpp"
|
||||
@ -77,6 +78,7 @@ struct MainScreen final : public Screen {
|
||||
|
||||
ChatGui4 cg;
|
||||
SettingsWindow sw;
|
||||
ObjectStoreUI osui;
|
||||
ToxUIUtils tuiu;
|
||||
ToxDHTCapHisto tdch;
|
||||
|
||||
|
104
src/object_store_ui.cpp
Normal file
104
src/object_store_ui.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include "./object_store_ui.hpp"
|
||||
|
||||
#include <solanaceae/util/utils.hpp>
|
||||
#include <solanaceae/object_store/meta_components.hpp>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
#include <solanaceae/message3/components.hpp>
|
||||
|
||||
namespace MM {
|
||||
|
||||
template<> void ComponentEditorWidget<ObjectStore::Components::ID>(entt::basic_registry<Object>& registry, Object entity) {
|
||||
auto& c = registry.get<ObjectStore::Components::ID>(entity);
|
||||
|
||||
const auto str = bin2hex(c.v);
|
||||
ImGui::TextUnformatted(str.c_str());
|
||||
}
|
||||
|
||||
template<> void ComponentEditorWidget<Message::Components::Transfer::FileInfo>(entt::basic_registry<Object>& registry, Object entity) {
|
||||
auto& c = registry.get<Message::Components::Transfer::FileInfo>(entity);
|
||||
|
||||
ImGui::Text("Total size: %lu", c.total_size);
|
||||
if (ImGui::BeginTable("file list", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("name", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("size", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (const auto& entry : c.file_list) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(entry.file_name.c_str());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%lu", entry.file_size);
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
template<> void ComponentEditorWidget<Message::Components::Transfer::FileInfoLocal>(entt::basic_registry<Object>& registry, Object entity) {
|
||||
auto& c = registry.get<Message::Components::Transfer::FileInfoLocal>(entity);
|
||||
|
||||
if (ImGui::BeginTable("file list", 1, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("name", ImGuiTableColumnFlags_WidthStretch);
|
||||
//ImGui::TableSetupColumn("size", ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for (const auto& entry : c.file_list) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(entry.c_str());
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
template<> void ComponentEditorWidget<Message::Components::Transfer::BytesReceived>(entt::basic_registry<Object>& registry, Object entity) {
|
||||
auto& c = registry.get<Message::Components::Transfer::BytesReceived>(entity);
|
||||
ImGui::Text("total bytes received: %lu", c.total);
|
||||
}
|
||||
|
||||
template<> void ComponentEditorWidget<Message::Components::Transfer::BytesSent>(entt::basic_registry<Object>& registry, Object entity) {
|
||||
auto& c = registry.get<Message::Components::Transfer::BytesSent>(entity);
|
||||
ImGui::Text("total bytes sent: %lu", c.total);
|
||||
}
|
||||
|
||||
} // MM
|
||||
|
||||
ObjectStoreUI::ObjectStoreUI(
|
||||
ObjectStore2& os
|
||||
) : _os(os) {
|
||||
_ee.show_window = false;
|
||||
|
||||
_ee.registerComponent<ObjectStore::Components::ID>("ID");
|
||||
_ee.registerComponent<ObjectStore::Components::DataCompressionType>("DataCompressionType");
|
||||
|
||||
_ee.registerComponent<Message::Components::Transfer::FileInfo>("Transfer::FileInfo");
|
||||
_ee.registerComponent<Message::Components::Transfer::FileInfoLocal>("Transfer::FileInfoLocal");
|
||||
_ee.registerComponent<Message::Components::Transfer::BytesReceived>("Transfer::BytesReceived");
|
||||
_ee.registerComponent<Message::Components::Transfer::BytesSent>("Transfer::BytesSent");
|
||||
}
|
||||
|
||||
void ObjectStoreUI::render(void) {
|
||||
{ // main window menubar injection
|
||||
// assumes the window "tomato" was rendered already by cg
|
||||
if (ImGui::Begin("tomato")) {
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
ImGui::Separator();
|
||||
if (ImGui::BeginMenu("ObjectStore")) {
|
||||
if (ImGui::MenuItem("Inspector")) {
|
||||
_ee.show_window = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
static Object selected_ent {entt::null};
|
||||
_ee.renderSimpleCombo(_os.registry(), selected_ent);
|
||||
}
|
||||
|
19
src/object_store_ui.hpp
Normal file
19
src/object_store_ui.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/object_store/object_store.hpp>
|
||||
|
||||
#include "./imgui_entt_entity_editor.hpp"
|
||||
|
||||
class ObjectStoreUI {
|
||||
ObjectStore2& _os;
|
||||
|
||||
MM::EntityEditor<Object> _ee;
|
||||
|
||||
public:
|
||||
ObjectStoreUI(
|
||||
ObjectStore2& os
|
||||
);
|
||||
|
||||
void render(void);
|
||||
};
|
||||
|
@ -50,6 +50,12 @@ StartScreen::StartScreen(const std::vector<std::string_view>& args, SDL_Renderer
|
||||
}
|
||||
}
|
||||
|
||||
{ // seed tox save path
|
||||
if (_conf.has_string("tox", "save_file_path")) {
|
||||
_tox_profile_path = _conf.get_string("tox", "save_file_path").value();
|
||||
}
|
||||
}
|
||||
|
||||
float display_scale = SDL_GetWindowDisplayScale(SDL_GetRenderWindow(renderer));
|
||||
if (display_scale < 0.001f) {
|
||||
// error?
|
||||
@ -134,6 +140,9 @@ StartScreen::StartScreen(const std::vector<std::string_view>& args, SDL_Renderer
|
||||
}
|
||||
|
||||
Screen* StartScreen::render(float, bool&) {
|
||||
const float TEXT_LOAD_WIDTH = ImGui::CalcTextSize("load").x;
|
||||
const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
|
||||
|
||||
|
||||
// TODO: imgui tox profile selector?
|
||||
|
||||
@ -246,7 +255,7 @@ Screen* StartScreen::render(float, bool&) {
|
||||
// load but file missing
|
||||
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("load", {60, 25});
|
||||
ImGui::Button("load", {TEXT_LOAD_WIDTH*1.5f, TEXT_BASE_HEIGHT*1.5f});
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||
@ -256,14 +265,14 @@ Screen* StartScreen::render(float, bool&) {
|
||||
// new but file exists
|
||||
|
||||
ImGui::BeginDisabled();
|
||||
ImGui::Button("load", {60, 25});
|
||||
ImGui::Button("load", {TEXT_LOAD_WIDTH*1.5f, TEXT_BASE_HEIGHT*1.5f});
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip | ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||
ImGui::SetTooltip("file already exists");
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Button("load", {60, 25})) {
|
||||
if (ImGui::Button("load", {TEXT_LOAD_WIDTH*1.5f, TEXT_BASE_HEIGHT*1.5f})) {
|
||||
|
||||
auto new_screen = std::make_unique<MainScreen>(std::move(_conf), _renderer, _theme, _tox_profile_path, _password, _user_name, queued_plugin_paths);
|
||||
return new_screen.release();
|
||||
|
@ -29,6 +29,9 @@ void ToxUIUtils::render(void) {
|
||||
if (ImGui::MenuItem("add Friend by ID")) {
|
||||
_show_add_friend_window = true;
|
||||
}
|
||||
if (ImGui::MenuItem("copy own ToxID")) {
|
||||
ImGui::SetClipboardText(_tc.toxSelfGetAddressStr().c_str());
|
||||
}
|
||||
if (ImGui::MenuItem("join Group by ID (ngc)")) {
|
||||
_show_add_group_window = true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user