087412d73a
- demos_text_editor.cpp: split horizontal con editor GLSL precargado a la izquierda (boton Save to /tmp/fn_demo.glsl + dirty indicator) y panel de eventos a la derecha (path, active flag, lista scrollable, boton clear). Watcher activo sobre /tmp/fn_demo.glsl; reintenta el add() tras el primer Save si el archivo no existia al iniciar. - demos.h: declaracion de gallery::demo_text_editor() - main.cpp: entry "text_editor"/"text_editor + watcher" en categoria Core - CMakeLists.txt: anade demos_text_editor.cpp + sources de text_editor, file_watcher y vendor TextEditor.cpp + include path de imgui_text_edit Nota: la primitives_gallery NO se construye en este branch (sus deps — button.cpp, toolbar.cpp, etc. — son untracked en master). El subdirectorio se anade pero protegido por FN_BUILD_GALLERY=OFF para no romper builds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
212 lines
6.9 KiB
C++
212 lines
6.9 KiB
C++
#include "demos.h"
|
|
#include "demo.h"
|
|
|
|
#include "viz/bar_chart.h"
|
|
#include "viz/pie_chart.h"
|
|
#include "viz/line_plot.h"
|
|
#include "viz/scatter_plot.h"
|
|
#include "viz/histogram.h"
|
|
#include "viz/sparkline.h"
|
|
#include "core/tokens.h"
|
|
|
|
#include <imgui.h>
|
|
#include <cmath>
|
|
#include <vector>
|
|
|
|
namespace gallery {
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// bar_chart
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void demo_bar_chart() {
|
|
demo_header("bar_chart", "v1.2.0",
|
|
"Barras verticales con ejes pineados, tooltip al hover y auto-rotacion 45 grados "
|
|
"de labels cuando no caben horizontalmente.");
|
|
|
|
section("Labels que caben horizontalmente");
|
|
{
|
|
const char* langs[] = {"go", "py", "ts", "sh", "cpp"};
|
|
float values[] = {412.0f, 187.0f, 94.0f, 63.0f, 36.0f};
|
|
bar_chart("##bar_short", langs, values, 5, 0.67f, 200.0f);
|
|
}
|
|
|
|
section("Labels largos que obligan a rotar");
|
|
{
|
|
const char* domains[] = {
|
|
"core", "infrastructure", "finance", "datascience",
|
|
"cybersecurity", "notebook", "browser"
|
|
};
|
|
float values[] = {412, 187, 94, 63, 42, 38, 22};
|
|
bar_chart("##bar_long", domains, values, 7, 0.67f, 240.0f);
|
|
}
|
|
|
|
code_block(
|
|
"const char* labels[] = {\"go\",\"py\",\"ts\",\"sh\",\"cpp\"};\n"
|
|
"float values[] = {412,187,94,63,36};\n"
|
|
"bar_chart(\"##lang\", labels, values, 5); // h=200 default\n"
|
|
"bar_chart(\"##lang\", labels, values, 5, 0.8f, 300); // bar_w + altura"
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// pie_chart
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void demo_pie_chart() {
|
|
demo_header("pie_chart", "v1.1.0",
|
|
"Pie/donut con aspect 1:1, ejes pineados y tooltip por slice con "
|
|
"valor absoluto + porcentaje.");
|
|
|
|
if (ImGui::BeginTable("##pie_grid", 2, ImGuiTableFlags_SizingStretchSame)) {
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
{
|
|
const char* labels[] = {"Pure", "Impure"};
|
|
float values[] = {412.0f, 278.0f};
|
|
variant_label("Pie (radius auto)");
|
|
pie_chart("##pie_auto", labels, values, 2, 0.0f, 260.0f);
|
|
}
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
|
{
|
|
const char* labels[] = {"function", "pipeline", "component"};
|
|
float values[] = {618.0f, 42.0f, 230.0f};
|
|
variant_label("Donut (radius = -0.45)");
|
|
pie_chart("##pie_donut", labels, values, 3, -0.45f, 260.0f);
|
|
}
|
|
|
|
ImGui::EndTable();
|
|
}
|
|
|
|
code_block(
|
|
"const char* labels[] = {\"Pure\",\"Impure\"};\n"
|
|
"float values[] = {412, 278};\n"
|
|
"pie_chart(\"##p\", labels, values, 2); // pie auto\n"
|
|
"pie_chart(\"##p\", labels, values, 2, -0.45f, 260); // donut"
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// line_plot
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void demo_line_plot() {
|
|
demo_header("line_plot", "v1.1.0",
|
|
"Line plot 2D con limites de ejes calculados de min/max y pineados. "
|
|
"Sin auto-fit animado, sin pan/zoom.");
|
|
|
|
constexpr int N = 100;
|
|
static float xs[N], ys[N];
|
|
static bool init = false;
|
|
if (!init) {
|
|
for (int i = 0; i < N; i++) {
|
|
xs[i] = static_cast<float>(i) * 0.1f;
|
|
ys[i] = std::sin(xs[i]) + 0.3f * std::sin(xs[i] * 3.5f);
|
|
}
|
|
init = true;
|
|
}
|
|
line_plot("##line", xs, ys, N, 240.0f);
|
|
|
|
code_block(
|
|
"line_plot(\"##series\", xs, ys, count); // h=200 default\n"
|
|
"line_plot(\"##series\", xs, ys, count, 300.0f); // custom height"
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// scatter_plot
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void demo_scatter_plot() {
|
|
demo_header("scatter_plot", "v1.1.0",
|
|
"Puntos dispersos con ejes pineados (5% headroom). Sin interaccion.");
|
|
|
|
constexpr int N = 120;
|
|
static float xs[N], ys[N];
|
|
static bool init = false;
|
|
if (!init) {
|
|
unsigned seed = 1234;
|
|
auto rnd = [&]() {
|
|
seed = seed * 1103515245u + 12345u;
|
|
return static_cast<float>((seed >> 16) & 0x7fff) / 32768.0f;
|
|
};
|
|
for (int i = 0; i < N; i++) {
|
|
xs[i] = rnd() * 10.0f;
|
|
ys[i] = 0.5f * xs[i] + rnd() * 3.0f;
|
|
}
|
|
init = true;
|
|
}
|
|
scatter_plot("##sc", xs, ys, N, 240.0f);
|
|
|
|
code_block(
|
|
"scatter_plot(\"##xy\", xs, ys, count, 240.0f);"
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// histogram
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void demo_histogram() {
|
|
demo_header("histogram", "v1.1.0",
|
|
"Histograma con bins automaticos (Sturges) o manuales. Usa AutoFit "
|
|
"para los bins + Lock para bloquear pan/zoom.");
|
|
|
|
constexpr int N = 300;
|
|
static float vals[N];
|
|
static bool init = false;
|
|
if (!init) {
|
|
unsigned seed = 42;
|
|
auto rnd = [&]() {
|
|
seed = seed * 1103515245u + 12345u;
|
|
return static_cast<float>((seed >> 16) & 0x7fff) / 32768.0f;
|
|
};
|
|
// Aproximacion de distribucion normal via box-muller simplificado
|
|
for (int i = 0; i < N; i++) {
|
|
float u1 = rnd() + 1e-6f;
|
|
float u2 = rnd();
|
|
vals[i] = std::sqrt(-2.0f * std::log(u1))
|
|
* std::cos(2.0f * 3.14159f * u2);
|
|
}
|
|
init = true;
|
|
}
|
|
histogram("##hist", vals, N, -1, 240.0f);
|
|
|
|
code_block(
|
|
"histogram(\"##h\", values, count); // bins=Sturges\n"
|
|
"histogram(\"##h\", values, count, 30, 300.0f); // 30 bins, h=300"
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// sparkline
|
|
// ---------------------------------------------------------------------------
|
|
|
|
void demo_sparkline() {
|
|
demo_header("sparkline", "v1.0.0",
|
|
"Mini grafico de lineas inline (rellenado con alpha + linea). "
|
|
"Pensado para tablas, KPI cards, headers.");
|
|
|
|
float up[] = {10, 12, 11, 15, 18, 17, 20};
|
|
float down[] = {30, 28, 29, 25, 22, 24, 20};
|
|
float flat[] = {10, 10, 10, 10, 10, 10, 10};
|
|
|
|
ImGui::Text("Trending up "); ImGui::SameLine();
|
|
sparkline("##up", up, 7, ImVec4(0.35f, 0.85f, 0.45f, 1.0f), 140.0f, 22.0f);
|
|
|
|
ImGui::Text("Trending down"); ImGui::SameLine();
|
|
sparkline("##down", down, 7, ImVec4(0.90f, 0.30f, 0.30f, 1.0f), 140.0f, 22.0f);
|
|
|
|
ImGui::Text("Flat "); ImGui::SameLine();
|
|
sparkline("##flat", flat, 7, ImVec4(0.55f, 0.55f, 0.55f, 1.0f), 140.0f, 22.0f);
|
|
|
|
code_block(
|
|
"float history[] = {10,12,11,15,18,17,20};\n"
|
|
"sparkline(\"##rev\", history, 7, /*color=*/{0.35,0.85,0.45,1}, 140, 22);"
|
|
);
|
|
}
|
|
|
|
} // namespace gallery
|