openurl file + starting with sending image file and pasting
This commit is contained in:
parent
89bc11eca7
commit
fc90106d83
@ -45,6 +45,9 @@ add_executable(tomato
|
|||||||
./file_selector.hpp
|
./file_selector.hpp
|
||||||
./file_selector.cpp
|
./file_selector.cpp
|
||||||
|
|
||||||
|
./send_image_popup.hpp
|
||||||
|
./send_image_popup.cpp
|
||||||
|
|
||||||
./chat_gui4.hpp
|
./chat_gui4.hpp
|
||||||
./chat_gui4.cpp
|
./chat_gui4.cpp
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace Components {
|
namespace Components {
|
||||||
|
|
||||||
@ -40,7 +43,7 @@ ChatGui4::ChatGui4(
|
|||||||
RegistryMessageModel& rmm,
|
RegistryMessageModel& rmm,
|
||||||
Contact3Registry& cr,
|
Contact3Registry& cr,
|
||||||
TextureUploaderI& tu
|
TextureUploaderI& tu
|
||||||
) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu), _msg_tc(_mil, tu) {
|
) : _conf(conf), _rmm(rmm), _cr(cr), _tal(_cr), _contact_tc(_tal, tu), _msg_tc(_mil, tu), _sip(tu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatGui4::render(void) {
|
void ChatGui4::render(void) {
|
||||||
@ -353,9 +356,60 @@ void ChatGui4::render(void) {
|
|||||||
[](){}
|
[](){}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// TODO: add support for more than images
|
||||||
|
// !!! polling each frame can be VERY expensive !!!
|
||||||
|
//const auto* mime_type = clipboardHasImage();
|
||||||
|
//ImGui::BeginDisabled(mime_type == nullptr);
|
||||||
|
if (ImGui::Button("paste\nfile", {-FLT_MIN, 0})) {
|
||||||
|
const auto* mime_type = clipboardHasImage();
|
||||||
|
if (mime_type != nullptr) { // making sure
|
||||||
|
size_t data_size = 0;
|
||||||
|
void* data = SDL_GetClipboardData(mime_type, &data_size);
|
||||||
|
|
||||||
|
std::cout << "CG: pasted image of size " << data_size << " mime " << mime_type << "\n";
|
||||||
|
|
||||||
|
_sip.sendMemory(
|
||||||
|
static_cast<const uint8_t*>(data), data_size,
|
||||||
|
[this](const auto& img_data, const auto file_ext) {
|
||||||
|
// create file name
|
||||||
|
// TODO: move this into sip
|
||||||
|
std::ostringstream tmp_file_name {"tomato_Image_", std::ios_base::ate};
|
||||||
|
{
|
||||||
|
const auto now = std::chrono::system_clock::now();
|
||||||
|
const auto ctime = std::chrono::system_clock::to_time_t(now);
|
||||||
|
tmp_file_name
|
||||||
|
<< std::put_time(std::localtime(&ctime), "%F_%H-%M-%S")
|
||||||
|
<< "."
|
||||||
|
<< std::setfill('0') << std::setw(4)
|
||||||
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch() - std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch())).count()
|
||||||
|
<< file_ext
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "tmp image path " << tmp_file_name.str() << "\n";
|
||||||
|
|
||||||
|
const std::filesystem::path tmp_send_file_path = "tmp_send_files";
|
||||||
|
std::filesystem::create_directories(tmp_send_file_path);
|
||||||
|
const auto tmp_file_path = tmp_send_file_path / tmp_file_name.str();
|
||||||
|
|
||||||
|
std::ofstream(tmp_file_path, std::ios_base::out | std::ios_base::binary)
|
||||||
|
.write(reinterpret_cast<const char*>(img_data.data()), img_data.size());
|
||||||
|
|
||||||
|
_rmm.sendFilePath(*_selected_contact, tmp_file_name.str(), tmp_file_path.u8string());
|
||||||
|
},
|
||||||
|
[](){}
|
||||||
|
);
|
||||||
|
SDL_free(data); // free data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//ImGui::EndDisabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
#if 0
|
||||||
// if preview window not open?
|
// if preview window not open?
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_V) && ImGui::IsKeyPressed(ImGuiMod_Shortcut, false)) {
|
if (ImGui::IsKeyPressed(ImGuiKey_V) && ImGui::IsKeyPressed(ImGuiMod_Shortcut, false)) {
|
||||||
std::cout << "CG: paste?\n";
|
std::cout << "CG: paste?\n";
|
||||||
@ -366,6 +420,7 @@ void ChatGui4::render(void) {
|
|||||||
std::cout << "CG: pasted image of size " << data_size << " mime " << mime_type << "\n";
|
std::cout << "CG: pasted image of size " << data_size << " mime " << mime_type << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
@ -373,6 +428,7 @@ void ChatGui4::render(void) {
|
|||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
_fss.render();
|
_fss.render();
|
||||||
|
_sip.render();
|
||||||
|
|
||||||
_contact_tc.workLoadQueue();
|
_contact_tc.workLoadQueue();
|
||||||
_msg_tc.workLoadQueue();
|
_msg_tc.workLoadQueue();
|
||||||
@ -523,8 +579,25 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
|||||||
// if has local, display save base path?
|
// if has local, display save base path?
|
||||||
|
|
||||||
for (size_t i = 0; i < file_list.size(); i++) {
|
for (size_t i = 0; i < file_list.size(); i++) {
|
||||||
// TODO: selectable text widget
|
ImGui::PushID(i);
|
||||||
|
|
||||||
|
// 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 (%lu)", file_list[i].file_name.c_str(), file_list[i].file_size);
|
||||||
|
|
||||||
|
if (reg.all_of<Message::Components::Transfer::FileInfoLocal>(e)) {
|
||||||
|
const auto& local_info = reg.get<Message::Components::Transfer::FileInfoLocal>(e);
|
||||||
|
if (local_info.file_list.size() > i && ImGui::BeginPopupContextItem("##file_c")) {
|
||||||
|
if (ImGui::MenuItem("open")) {
|
||||||
|
std::string url{"file://" + std::filesystem::canonical(local_info.file_list.at(i)).u8string()};
|
||||||
|
std::cout << "opening file '" << url << "'\n";
|
||||||
|
|
||||||
|
SDL_OpenURL(url.c_str());
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_list.size() == 1 && reg.all_of<Message::Components::Transfer::FileInfoLocal, Message::Components::FrameDims>(e)) {
|
if (file_list.size() == 1 && reg.all_of<Message::Components::Transfer::FileInfoLocal, Message::Components::FrameDims>(e)) {
|
||||||
@ -546,6 +619,7 @@ void ChatGui4::renderMessageBodyFile(Message3Registry& reg, const Message3 e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Image(id, ImVec2{static_cast<float>(width), static_cast<float>(height)});
|
ImGui::Image(id, ImVec2{static_cast<float>(width), static_cast<float>(height)});
|
||||||
|
// TODO: clickable to open in internal image viewer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,6 +737,9 @@ bool ChatGui4::renderContactListContactBig(const Contact3 c, const bool selected
|
|||||||
color_current
|
color_current
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: move this out of chat gui
|
||||||
|
any_unread = false;
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
{
|
{
|
||||||
@ -681,6 +758,7 @@ bool ChatGui4::renderContactListContactBig(const Contact3 c, const bool selected
|
|||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
#endif
|
#endif
|
||||||
has_unread = true;
|
has_unread = true;
|
||||||
|
any_unread = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "./tox_avatar_loader.hpp"
|
#include "./tox_avatar_loader.hpp"
|
||||||
#include "./message_image_loader.hpp"
|
#include "./message_image_loader.hpp"
|
||||||
#include "./file_selector.hpp"
|
#include "./file_selector.hpp"
|
||||||
|
#include "./send_image_popup.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -23,6 +24,7 @@ class ChatGui4 {
|
|||||||
TextureCache<void*, Message3Handle, MessageImageLoader> _msg_tc;
|
TextureCache<void*, Message3Handle, MessageImageLoader> _msg_tc;
|
||||||
|
|
||||||
FileSelector _fss;
|
FileSelector _fss;
|
||||||
|
SendImagePopup _sip;
|
||||||
|
|
||||||
std::optional<Contact3> _selected_contact;
|
std::optional<Contact3> _selected_contact;
|
||||||
|
|
||||||
@ -45,6 +47,9 @@ class ChatGui4 {
|
|||||||
public:
|
public:
|
||||||
void render(void);
|
void render(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool any_unread {false};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void renderMessageBodyText(Message3Registry& reg, const Message3 e);
|
void renderMessageBodyText(Message3Registry& reg, const Message3 e);
|
||||||
void renderMessageBodyFile(Message3Registry& reg, const Message3 e);
|
void renderMessageBodyFile(Message3Registry& reg, const Message3 e);
|
||||||
|
@ -9,6 +9,7 @@ struct ImageLoaderI {
|
|||||||
struct ImageInfo {
|
struct ImageInfo {
|
||||||
uint32_t width {0};
|
uint32_t width {0};
|
||||||
uint32_t height {0};
|
uint32_t height {0};
|
||||||
|
const char* file_ext {nullptr};
|
||||||
};
|
};
|
||||||
virtual ImageInfo loadInfoFromMemory(const uint8_t* data, uint64_t data_size) = 0;
|
virtual ImageInfo loadInfoFromMemory(const uint8_t* data, uint64_t data_size) = 0;
|
||||||
|
|
||||||
@ -20,6 +21,7 @@ struct ImageLoaderI {
|
|||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
};
|
};
|
||||||
std::vector<Frame> frames;
|
std::vector<Frame> frames;
|
||||||
|
const char* file_ext {nullptr};
|
||||||
};
|
};
|
||||||
virtual ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) = 0;
|
virtual ImageResult loadFromMemoryRGBA(const uint8_t* data, uint64_t data_size) = 0;
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,7 @@ ImageLoaderSDLBMP::ImageInfo ImageLoaderSDLBMP::loadInfoFromMemory(const uint8_t
|
|||||||
|
|
||||||
res.width = surf->w;
|
res.width = surf->w;
|
||||||
res.height = surf->h;
|
res.height = surf->h;
|
||||||
|
res.file_ext = "bmp";
|
||||||
|
|
||||||
SDL_DestroySurface(surf);
|
SDL_DestroySurface(surf);
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ ImageLoaderSDLBMP::ImageResult ImageLoaderSDLBMP::loadFromMemoryRGBA(const uint8
|
|||||||
|
|
||||||
res.width = surf->w;
|
res.width = surf->w;
|
||||||
res.height = surf->h;
|
res.height = surf->h;
|
||||||
|
res.file_ext = "bmp";
|
||||||
|
|
||||||
SDL_LockSurface(conv_surf);
|
SDL_LockSurface(conv_surf);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ ImageLoaderSTB::ImageResult ImageLoaderSTB::loadFromMemoryRGBA(const uint8_t* da
|
|||||||
if (img_data) {
|
if (img_data) {
|
||||||
res.width = x;
|
res.width = x;
|
||||||
res.height = y;
|
res.height = y;
|
||||||
|
res.file_ext = "gif";
|
||||||
|
|
||||||
const size_t stride = x * y * 4;
|
const size_t stride = x * y * 4;
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ ImageLoaderWebP::ImageInfo ImageLoaderWebP::loadInfoFromMemory(const uint8_t* da
|
|||||||
WebPAnimDecoderGetInfo(dec, &anim_info);
|
WebPAnimDecoderGetInfo(dec, &anim_info);
|
||||||
res.width = anim_info.canvas_width;
|
res.width = anim_info.canvas_width;
|
||||||
res.height = anim_info.canvas_height;
|
res.height = anim_info.canvas_height;
|
||||||
|
res.file_ext = "webp";
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -53,6 +54,7 @@ ImageLoaderWebP::ImageResult ImageLoaderWebP::loadFromMemoryRGBA(const uint8_t*
|
|||||||
WebPAnimDecoderGetInfo(dec, &anim_info);
|
WebPAnimDecoderGetInfo(dec, &anim_info);
|
||||||
res.width = anim_info.canvas_width;
|
res.width = anim_info.canvas_width;
|
||||||
res.height = anim_info.canvas_height;
|
res.height = anim_info.canvas_height;
|
||||||
|
res.file_ext = "webp";
|
||||||
|
|
||||||
int prev_timestamp = 0;
|
int prev_timestamp = 0;
|
||||||
while (WebPAnimDecoderHasMoreFrames(dec)) {
|
while (WebPAnimDecoderHasMoreFrames(dec)) {
|
||||||
|
166
src/send_image_popup.cpp
Normal file
166
src/send_image_popup.cpp
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
#include "./send_image_popup.hpp"
|
||||||
|
|
||||||
|
#include "./image_loader_sdl_bmp.hpp"
|
||||||
|
#include "./image_loader_stb.hpp"
|
||||||
|
#include "./image_loader_webp.hpp"
|
||||||
|
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
|
SendImagePopup::SendImagePopup(TextureUploaderI& tu) : _tu(tu) {
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderSDLBMP>());
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderWebP>());
|
||||||
|
_image_loaders.push_back(std::make_unique<ImageLoaderSTB>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendImagePopup::reset(void) {
|
||||||
|
_on_send = [](const auto&, auto){};
|
||||||
|
_on_cancel = [](){};
|
||||||
|
|
||||||
|
// hm
|
||||||
|
original_data.clear();
|
||||||
|
{
|
||||||
|
original_image.width = 0;
|
||||||
|
original_image.height = 0;
|
||||||
|
original_image.frames.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear preview img
|
||||||
|
for (const auto& tex_id : preview_image.textures) {
|
||||||
|
_tu.destroy(tex_id);
|
||||||
|
}
|
||||||
|
preview_image = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SendImagePopup::load(void) {
|
||||||
|
// try all loaders after another
|
||||||
|
for (auto& il : _image_loaders) {
|
||||||
|
original_image = il->loadFromMemoryRGBA(original_data.data(), original_data.size());
|
||||||
|
if (original_image.frames.empty() || original_image.height == 0 || original_image.width == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
original_file_ext = ".";
|
||||||
|
if (original_image.file_ext != nullptr) {
|
||||||
|
original_file_ext += original_image.file_ext;
|
||||||
|
} else {
|
||||||
|
original_file_ext += "unk";
|
||||||
|
}
|
||||||
|
|
||||||
|
preview_image.timestamp_last_rendered = getNowMS();
|
||||||
|
preview_image.current_texture = 0;
|
||||||
|
for (const auto& [ms, data] : original_image.frames) {
|
||||||
|
const auto n_t = _tu.uploadRGBA(data.data(), original_image.width, original_image.height);
|
||||||
|
preview_image.textures.push_back(n_t);
|
||||||
|
preview_image.frame_duration.push_back(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// redundant
|
||||||
|
preview_image.width = original_image.width;
|
||||||
|
preview_image.height = original_image.height;
|
||||||
|
|
||||||
|
if (original_image.frames.size() > 1) {
|
||||||
|
std::cout << "SIP: loaded animation\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "SIP: loaded image\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendImagePopup::sendMemory(
|
||||||
|
const uint8_t* data, size_t data_size,
|
||||||
|
std::function<void(const std::vector<uint8_t>&, std::string_view)>&& on_send,
|
||||||
|
std::function<void(void)>&& on_cancel
|
||||||
|
) {
|
||||||
|
original_raw = false;
|
||||||
|
if (data == nullptr || data_size == 0) {
|
||||||
|
return; // error
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy paste data to memory
|
||||||
|
original_data.clear();
|
||||||
|
original_data.insert(original_data.begin(), data, data+data_size);
|
||||||
|
|
||||||
|
if (!load()) {
|
||||||
|
std::cerr << "SIP: failed to load image from memory\n";
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_open_popup = true;
|
||||||
|
|
||||||
|
_on_send = std::move(on_send);
|
||||||
|
_on_cancel = std::move(on_cancel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SendImagePopup::render(void) {
|
||||||
|
if (_open_popup) {
|
||||||
|
_open_popup = false;
|
||||||
|
ImGui::OpenPopup("send image##SendImagePopup");
|
||||||
|
|
||||||
|
//const auto TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
|
||||||
|
//const auto TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
|
//ImGui::SetNextWindowSize({TEXT_BASE_WIDTH*100, TEXT_BASE_HEIGHT*30});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add cancel action
|
||||||
|
if (ImGui::BeginPopupModal("send image##SendImagePopup", nullptr/*, ImGuiWindowFlags_NoDecoration*/)) {
|
||||||
|
const auto TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
|
||||||
|
const auto TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
|
||||||
|
|
||||||
|
preview_image.doAnimation(getNowMS());
|
||||||
|
|
||||||
|
//ImGui::Text("send file....\n......");
|
||||||
|
|
||||||
|
{
|
||||||
|
float width = ImGui::GetWindowContentRegionMax().x - ImGui::GetWindowContentRegionMin().x;
|
||||||
|
float height = preview_image.height * (width / preview_image.width);
|
||||||
|
|
||||||
|
const float max_height =
|
||||||
|
ImGui::GetWindowContentRegionMax().y
|
||||||
|
- (
|
||||||
|
ImGui::GetWindowContentRegionMin().y
|
||||||
|
+ TEXT_BASE_HEIGHT*(2-1) // row of buttons (-1 bc fh inclues fontsize)
|
||||||
|
+ ImGui::GetFrameHeightWithSpacing()
|
||||||
|
)
|
||||||
|
;
|
||||||
|
if (height > max_height) {
|
||||||
|
width *= max_height / height;
|
||||||
|
height = max_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: propergate type
|
||||||
|
ImGui::Image(
|
||||||
|
preview_image.getID<void*>(),
|
||||||
|
ImVec2{static_cast<float>(width), static_cast<float>(height)}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button("X cancel", {ImGui::GetWindowContentRegionWidth()/2.f, TEXT_BASE_HEIGHT*2})) {
|
||||||
|
_on_cancel();
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("send ->", {-FLT_MIN, TEXT_BASE_HEIGHT*2})) {
|
||||||
|
//if (_is_valid(_current_file_path)) {
|
||||||
|
|
||||||
|
// if modified
|
||||||
|
//_on_send(data);
|
||||||
|
// else
|
||||||
|
_on_send(original_data, original_file_ext);
|
||||||
|
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
reset();
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
61
src/send_image_popup.hpp
Normal file
61
src/send_image_popup.hpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "./image_loader.hpp"
|
||||||
|
#include "./texture_cache.hpp"
|
||||||
|
|
||||||
|
struct SendImagePopup {
|
||||||
|
TextureUploaderI& _tu;
|
||||||
|
|
||||||
|
// private
|
||||||
|
std::vector<std::unique_ptr<ImageLoaderI>> _image_loaders;
|
||||||
|
|
||||||
|
// copy of the original data, dont touch!
|
||||||
|
std::vector<uint8_t> original_data;
|
||||||
|
bool original_raw {false};
|
||||||
|
std::string original_file_ext; // if !original_raw
|
||||||
|
|
||||||
|
ImageLoaderI::ImageResult original_image;
|
||||||
|
|
||||||
|
struct Rect {
|
||||||
|
uint32_t x {0};
|
||||||
|
uint32_t y {0};
|
||||||
|
|
||||||
|
uint32_t w {0};
|
||||||
|
uint32_t h {0};
|
||||||
|
};
|
||||||
|
Rect crop_rect;
|
||||||
|
|
||||||
|
// texture to render (orig img)
|
||||||
|
TextureEntry preview_image;
|
||||||
|
|
||||||
|
bool _open_popup {false};
|
||||||
|
|
||||||
|
std::function<void(const std::vector<uint8_t>&, std::string_view)> _on_send = [](const auto&, auto){};
|
||||||
|
std::function<void(void)> _on_cancel = [](){};
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
|
||||||
|
// loads the image in original_data
|
||||||
|
// fills in original_image, preview_image and crop_rect
|
||||||
|
// returns if loaded successfully
|
||||||
|
bool load(void);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SendImagePopup(TextureUploaderI& tu);
|
||||||
|
|
||||||
|
void sendMemory(
|
||||||
|
const uint8_t* data, size_t data_size,
|
||||||
|
std::function<void(const std::vector<uint8_t>&, std::string_view)>&& on_send,
|
||||||
|
std::function<void(void)>&& on_cancel
|
||||||
|
);
|
||||||
|
// from memory_raw
|
||||||
|
// from file_path
|
||||||
|
|
||||||
|
// call this each frame
|
||||||
|
void render(void);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user