From f8b9c88e2cf855f6dcd264558e40bd2ecfdcef6a Mon Sep 17 00:00:00 2001
From: "Zed A. Shaw" <zed.shaw@gmail.com>
Date: Mon, 5 May 2025 14:26:47 -0400
Subject: [PATCH] First cut of a basic calculator UI example.

---
 assets/shaders.json | 12 ---------
 constants.hpp       |  4 ---
 demos/calc.cpp      | 64 +++++++++++++++++++++++++++++++++++++++++++++
 guecs.cpp           |  5 ++++
 guecs.hpp           |  4 +++
 5 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/assets/shaders.json b/assets/shaders.json
index 7a03ad7..825dbba 100644
--- a/assets/shaders.json
+++ b/assets/shaders.json
@@ -6,17 +6,5 @@
   "ERROR": {
     "file_name": "assets/shaders/ui_error.frag",
     "type": "fragment"
-  },
-  "rayview_sprites": {
-    "file_name": "assets/shaders/rayview_sprites.frag",
-    "type": "fragment"
-  },
-  "flame": {
-    "file_name": "assets/shaders/flame_trash.frag",
-    "type": "fragment"
-  },
-  "lightning": {
-    "file_name": "assets/shaders/lightning_attack.frag",
-    "type": "fragment"
   }
 }
diff --git a/constants.hpp b/constants.hpp
index 5372164..da3898a 100644
--- a/constants.hpp
+++ b/constants.hpp
@@ -3,15 +3,11 @@
 #include <string>
 #include <array>
 
-constexpr const int TEXTURE_WIDTH=256;
-constexpr const int TEXTURE_HEIGHT=256;
 constexpr const int SCREEN_WIDTH=1280;
 constexpr const int SCREEN_HEIGHT=720;
 
 constexpr const bool VSYNC=false;
 constexpr const int FRAME_LIMIT=60;
-constexpr const int NUM_SPRITES=1;
-constexpr const int MAX_LOG_MESSAGES=17;
 
 #ifdef NDEBUG
 constexpr const bool DEBUG_BUILD=false;
diff --git a/demos/calc.cpp b/demos/calc.cpp
index 07f5ce6..6556aa5 100644
--- a/demos/calc.cpp
+++ b/demos/calc.cpp
@@ -3,6 +3,48 @@
 #include "sfml/shaders.hpp"
 #include "sfml/textures.hpp"
 #include "guecs.hpp"
+#include "constants.hpp"
+
+constexpr const int WINDOW_WIDTH=300;
+constexpr const int WINDOW_HEIGHT=400;
+
+struct Calculator {
+  guecs::UI $gui;
+
+  Calculator() {
+    $gui.position(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
+    $gui.layout(
+        "[readout]"
+        "[btn7|btn8|btn9|mult]"
+        "[btn4|btn5|btn6|minus]"
+        "[btn1|btn2|btn3|plus]"
+        "[neg|btn0|dot|eq]");
+  }
+
+  void init() {
+    $gui.set<guecs::Background>($gui.MAIN, {});
+
+    for(auto& [name, cell] : $gui.cells()) {
+      auto id = $gui.entity(name);
+      $gui.set<guecs::Rectangle>(id, {});
+      $gui.set<guecs::Label>(id, {guecs::to_wstring(name)});
+      $gui.set<guecs::Clickable>(id, {
+          [=](auto, auto) { fmt::println("clicked {}", name); }
+      });
+    }
+
+    $gui.init();
+  }
+
+  void render(sf::RenderWindow& window) {
+    $gui.render(window);
+    // $gui.debug_layout(window);
+  }
+
+  void mouse(float x, float y, bool hover) {
+    $gui.mouse(x, y, hover);
+  }
+};
 
 
 int main() {
@@ -10,6 +52,28 @@ int main() {
   shaders::init();
   textures::init();
 
+  sf::RenderWindow window(sf::VideoMode({WINDOW_WIDTH, WINDOW_HEIGHT}), "LEL-GUECS Calculator");
+  window.setFramerateLimit(FRAME_LIMIT);
+  window.setVerticalSyncEnabled(VSYNC);
+
+  Calculator calc;
+  calc.init();
+
+  while(window.isOpen()) {
+    while (const auto event = window.pollEvent()) {
+      if(event->is<sf::Event::Closed>()) {
+        window.close();
+      }
 
+      if(const auto* mouse = event->getIf<sf::Event::MouseButtonPressed>()) {
+        if(mouse->button == sf::Mouse::Button::Left) {
+          sf::Vector2f pos = window.mapPixelToCoords(mouse->position);
+          calc.mouse(pos.x, pos.y, false);
+        }
+      }
+    }
 
+    calc.render(window);
+    window.display();
+  }
 }
diff --git a/guecs.cpp b/guecs.cpp
index 03fd460..16963a4 100644
--- a/guecs.cpp
+++ b/guecs.cpp
@@ -220,4 +220,9 @@ namespace guecs {
       set<Label>(ent, to_set);
     }
   }
+
+  wstring to_wstring(const string& str) {
+    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
+    return $converter.from_bytes(str);
+  }
 }
diff --git a/guecs.hpp b/guecs.hpp
index bac396a..fc560c2 100644
--- a/guecs.hpp
+++ b/guecs.hpp
@@ -226,4 +226,8 @@ namespace guecs {
       void show_text(const string& region, const wstring& content);
       void show_label(const string& region, const wstring& content);
   };
+
+
+  wstring to_wstring(const string& str);
+
 }