<commit_before>#include <sf2/sf2.hpp>

#include <mirrage/gui/gui.hpp>

#include <mirrage/asset/asset_manager.hpp>
#include <mirrage/input/events.hpp>
#include <mirrage/input/input_manager.hpp>
#include <mirrage/utils/ranges.hpp>

#include <SDL.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>

#include <cstdint>
#include <string>

#ifdef _WIN32
#include "SDL_syswm.h"
#endif


extern void ref_embedded_assets_mirrage_gui();

namespace ImGui {

	void PositionNextWindow(glm::vec2 size, WindowPosition_X x, WindowPosition_Y y, glm::vec2 offset)
	{
		auto sw = GetIO().DisplaySize.x;
		auto sh = GetIO().DisplaySize.y;

		SetNextWindowSize(ImVec2(size.x, size.y), ImGuiCond_Once);

		auto position = ImVec2(offset.x, offset.y);
		switch(x) {
			case WindowPosition_X::left: position.x += 0.f; break;
			case WindowPosition_X::right: position.x += sw - size.x; break;
			case WindowPosition_X::center: position.x += sw / 2.f - size.x / 2.f; break;
		}

		switch(y) {
			case WindowPosition_Y::top: position.y += 0.f; break;
			case WindowPosition_Y::bottom: position.y += sh - size.y; break;
			case WindowPosition_Y::center: position.y += sh / 2.f - size.y / 2.f; break;
		}

		SetNextWindowPos(position, ImGuiCond_Once);
	}

	void BeginTable(const char*                   id,
	                std::initializer_list<Column> columns,
	                bool                          first_call,
	                bool                          border,
	                bool                          separator)
	{
		ImGui::Columns(int(columns.size()), id, border);

		if(separator)
			ImGui::Separator();

		float       offset = 0.0f;
		ImGuiStyle& style  = ImGui::GetStyle();

		for(auto& column : columns) {
			if(first_call) {
				auto width = column.size >= 0 ? column.size
				                              : (ImGui::CalcTextSize(column.header, nullptr, true).x
				                                 + 2 * style.ItemSpacing.x);

				ImGui::SetColumnOffset(-1, offset);
				ImGui::SetColumnWidth(-1, width);

				offset += width;
			}
			ImGui::Text("%s", column.header);
			ImGui::NextColumn();
		}

		if(separator)
			ImGui::Separator();
	}

	float ValueSliderFloat(
	        const char* label, float v, float v_min, float v_max, const char* format, float power)
	{
		SliderFloat(label, &v, v_min, v_max, format, power);
		return v;
	}

	namespace {
		auto scale_image(glm::vec2 img_size, glm::vec2 size, Image_scaling scaling)
		{
			switch(scaling) {
				case Image_scaling::fill_min:
					scaling = size.x < size.y ? Image_scaling::fill_x : Image_scaling::fill_y;
					break;
				case Image_scaling::fill_max:
					scaling = size.x > size.y ? Image_scaling::fill_x : Image_scaling::fill_y;
					break;
				default: break;
			}
			switch(scaling) {
				case Image_scaling::fill_x: size.y = img_size.y * size.x / img_size.x; break;
				case Image_scaling::fill_y: size.x = img_size.x * size.y / img_size.y; break;
				default: break;
			}

			return size;
		}
	} // namespace

	void DrawImage(
	        mirrage::gui::Gui& gui, void* image, glm::vec2 center, glm::vec2 size, Image_scaling scaling)
	{
		gui.texture_size(image).process([&](auto& img_size) {
			size = scale_image(img_size, size, scaling);

			auto p_min = center - size / 2.f;
			auto p_max = center + size / 2.f;
			ImGui::GetWindowDrawList()->AddImage(image, ImVec2(p_min.x, p_min.y), ImVec2(p_max.x, p_max.y));
		});
	}

	void BackgroundImage(mirrage::gui::Gui& gui, void* image, Image_scaling scaling)
	{
		auto size = glm::vec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y);

		ImGui::PositionNextWindow(size, ImGui::WindowPosition_X::center, ImGui::WindowPosition_Y::center);
		if(ImGui::Begin("##bg",
		                nullptr,
		                ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize
		                        | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus
		                        | ImGuiWindowFlags_NoFocusOnAppearing)) {
			DrawImage(gui, image, size / 2.f, size, scaling);
		}
		ImGui::End();
	}

	bool TexturedButton(mirrage::gui::Gui& gui,
	                    const char*        label,
	                    void*              texture_id,
	                    glm::vec2          size,
	                    Image_scaling      scaling)
	{
		return gui.texture_size(texture_id).process(false, [&](auto& img_size) {
			if(size.x > 0 && size.y > 0)
				size = scale_image(img_size, size, scaling);
			else if(size.x > 0)
				size.y = img_size.y * size.x / img_size.x;
			else if(size.y > 0)
				size.x = img_size.x * size.y / img_size.y;
			else
				size = img_size;

			ImGuiWindow* window = GetCurrentWindow();
			if(window->SkipItems)
				return false;

			const ImGuiID id         = window->GetID(label);
			const ImVec2  label_size = CalcTextSize(label, NULL, true);

			const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size));
			ItemSize(bb);
			if(!ItemAdd(bb, id))
				return false;

			bool hovered, held;
			bool pressed = ButtonBehavior(bb, id, &hovered, &held);

			// Render
			if(hovered) {
				window->DrawList->AddImage(texture_id, bb.Min, bb.Max, ImVec2(0, 0.5f), ImVec2(1, 1));
			} else {
				window->DrawList->AddImage(texture_id, bb.Min, bb.Max, ImVec2(0, 0), ImVec2(1, 0.5f));
			}

			auto text_pos_x = bb.Min.x + (bb.Max.x - bb.Min.x) / 2.f - label_size.x / 2.f;
			auto text_pos_y = bb.Min.y + (bb.Max.y - bb.Min.y) / 2.f - label_size.y / 2.f;
			window->DrawList->AddText(
			        ImVec2(text_pos_x, text_pos_y), GetColorU32(ImGuiCol_Text), label, nullptr);

			return pressed;
		});
	}
} // namespace ImGui


// copied from imgui_stdlib.cpp
struct InputTextCallback_UserData {
	std::string*           Str;
	ImGuiInputTextCallback ChainCallback;<commit_msg>fixed clang compiler warning<commit_after>#include <sf2/sf2.hpp>

#include <mirrage/gui/gui.hpp>

#include <mirrage/asset/asset_manager.hpp>
#include <mirrage/input/events.hpp>
#include <mirrage/input/input_manager.hpp>
#include <mirrage/utils/ranges.hpp>

#include <SDL.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>

#include <cstdint>
#include <string>

#ifdef _WIN32
#include "SDL_syswm.h"
#endif


extern void ref_embedded_assets_mirrage_gui();

namespace ImGui {

	void PositionNextWindow(glm::vec2 size, WindowPosition_X x, WindowPosition_Y y, glm::vec2 offset)
	{
		auto sw = GetIO().DisplaySize.x;
		auto sh = GetIO().DisplaySize.y;

		SetNextWindowSize(ImVec2(size.x, size.y), ImGuiCond_Once);

		auto position = ImVec2(offset.x, offset.y);
		switch(x) {
			case WindowPosition_X::left: position.x += 0.f; break;
			case WindowPosition_X::right: position.x += sw - size.x; break;
			case WindowPosition_X::center: position.x += sw / 2.f - size.x / 2.f; break;
		}

		switch(y) {
			case WindowPosition_Y::top: position.y += 0.f; break;
			case WindowPosition_Y::bottom: position.y += sh - size.y; break;
			case WindowPosition_Y::center: position.y += sh / 2.f - size.y / 2.f; break;
		}

		SetNextWindowPos(position, ImGuiCond_Once);
	}

	void BeginTable(const char*                   id,
	                std::initializer_list<Column> columns,
	                bool                          first_call,
	                bool                          border,
	                bool                          separator)
	{
		ImGui::Columns(int(columns.size()), id, border);

		if(separator)
			ImGui::Separator();

		float       offset = 0.0f;
		ImGuiStyle& style  = ImGui::GetStyle();

		for(auto& column : columns) {
			if(first_call) {
				auto width = column.size >= 0 ? column.size
				                              : (ImGui::CalcTextSize(column.header, nullptr, true).x
				                                 + 2 * style.ItemSpacing.x);

				ImGui::SetColumnOffset(-1, offset);
				ImGui::SetColumnWidth(-1, width);

				offset += width;
			}
			ImGui::Text("%s", column.header);
			ImGui::NextColumn();
		}

		if(separator)
			ImGui::Separator();
	}

	float ValueSliderFloat(
	        const char* label, float v, float v_min, float v_max, const char* format, float power)
	{
		SliderFloat(label, &v, v_min, v_max, format, power);
		return v;
	}

	namespace {
		auto scale_image(glm::vec2 img_size, glm::vec2 size, Image_scaling scaling)
		{
			switch(scaling) {
				case Image_scaling::fill_min:
					scaling = size.x < size.y ? Image_scaling::fill_x : Image_scaling::fill_y;
					break;
				case Image_scaling::fill_max:
					scaling = size.x > size.y ? Image_scaling::fill_x : Image_scaling::fill_y;
					break;
				default: break;
			}
			switch(scaling) {
				case Image_scaling::fill_x: size.y = img_size.y * size.x / img_size.x; break;
				case Image_scaling::fill_y: size.x = img_size.x * size.y / img_size.y; break;
				default: break;
			}

			return size;
		}
	} // namespace

	void DrawImage(
	        mirrage::gui::Gui& gui, void* image, glm::vec2 center, glm::vec2 size, Image_scaling scaling)
	{
		gui.texture_size(image).process([&](auto& img_size) {
			size = scale_image(img_size, size, scaling);

			auto p_min = center - size / 2.f;
			auto p_max = center + size / 2.f;
			ImGui::GetWindowDrawList()->AddImage(image, ImVec2(p_min.x, p_min.y), ImVec2(p_max.x, p_max.y));
		});
	}

	void BackgroundImage(mirrage::gui::Gui& gui, void* image, Image_scaling scaling)
	{
		auto size = glm::vec2(ImGui::GetIO().DisplaySize.x, ImGui::GetIO().DisplaySize.y);

		ImGui::PositionNextWindow(size, ImGui::WindowPosition_X::center, ImGui::WindowPosition_Y::center);
		if(ImGui::Begin("##bg",
		                nullptr,
		                ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize
		                        | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoBringToFrontOnFocus
		                        | ImGuiWindowFlags_NoFocusOnAppearing)) {
			DrawImage(gui, image, size / 2.f, size, scaling);
		}
		ImGui::End();
	}

	bool TexturedButton(mirrage::gui::Gui& gui,
	                    const char*        label,
	                    void*              texture_id,
	                    glm::vec2          size,
	                    Image_scaling      scaling)
	{
		return gui.texture_size(texture_id).process(false, [&](auto& img_size) {
			if(size.x > 0 && size.y > 0)
				size = scale_image(img_size, size, scaling);
			else if(size.x > 0)
				size.y = img_size.y * size.x / img_size.x;
			else if(size.y > 0)
				size.x = img_size.x * size.y / img_size.y;
			else
				size = img_size;

			ImGuiWindow* window = GetCurrentWindow();
			if(window->SkipItems)
				return false;

			const ImGuiID id         = window->GetID(label);
			const ImVec2  label_size = CalcTextSize(label, nullptr, true);

			const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size));
			ItemSize(bb);
			if(!ItemAdd(bb, id))
				return false;

			bool hovered, held;
			bool pressed = ButtonBehavior(bb, id, &hovered, &held);

			// Render
			if(hovered) {
				window->DrawList->AddImage(texture_id, bb.Min, bb.Max, ImVec2(0, 0.5f), ImVec2(1, 1));
			} else {
				window->DrawList->AddImage(texture_id, bb.Min, bb.Max, ImVec2(0, 0), ImVec2(1, 0.5f));
			}

			auto text_pos_x = bb.Min.x + (bb.Max.x - bb.Min.x) / 2.f - label_size.x / 2.f;
			auto text_pos_y = bb.Min.y + (bb.Max.y - bb.Min.y) / 2.f - label_size.y / 2.f;
			window->DrawList->AddText(
			        ImVec2(text_pos_x, text_pos_y), GetColorU32(ImGuiCol_Text), label, nullptr);

			return pressed;
		});
	}
} // namespace ImGui


// copied from imgui_stdlib.cpp
struct InputTextCallback_UserData {
	std::string*           Str;
	ImGuiInputTextCallback ChainCallback;
{'fraction_non_alphanumeric': 0.13709677419354838, 'fraction_numerical': 0.009951956074124914, 'mean_word_length': 2.7773817239144525, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6059661', 'n_tokens_mistral': 4665, 'n_tokens_neox': 4073, 'n_words': 820}