SkillAgentSearch skills...

Gempyre

Gempyre UI Framework for C++ (and Python)

Install / Use

/learn @mmertama/Gempyre
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

wqe

Gempyre

UI Framework

Gempyre is a UI multiplatform framework. Supporting Windows, Mac OSX, Linux, Raspberry OS and Android. Gempyre is minimalistic and simple; It is a UI framework without widgets - instead, the UI is composed using common web tools and frameworks. Therefore Gempyre is small, easy to learn and quick to take in use.

For the application, Gempyre let engine to be implemented using C++ (or Python), the UI can be constructed using CSS and HTML like any front end. All common tools from the web technologies are be available. Gempyre library provides a simple and easy C++ API for a application development and the whole API is only a few dozen calls.

Gempyre is intended for applications that has a solid C++ core (or C), and allows rapid UI development without extra hassle with platform specific UI development.

Gempyre is multiplatform, its core is built using C++20 (tested on OSX (CLang), Ubuntu (gcc), Raspberry OS (gcc) and Windows 10 (MSVC and MinGW) ). The Gempyre framework can be downloaded at Github under MIT license.

Gempyre itself does not contain an application window. The UI is drawn using external application. Some OSes defaults to system browser, some Python webview. However that is fully configurable per application.

Gempyre is a library that is linked with the application, except for Android, see Gempyre-Android. For Python, install Gempyre-Python on top of Gempyre library.

Gempyre API

Gempyre is minimum C++ level is C++17, but works with C++20 and C++23 as well.

  • gempyre.h, core classes for the application development.
  • gempyre_utils.h, miscellaneous collection of helper functions. These are not available for Python as there are plenty of analogous functionality.
  • gempyre_graphics.h, HTML canvas functions for bitmap and vector graphics.
  • gempyre_client.h, file dialogs for Gempyre application. Not available when system browser is used as an application window.

Gempyre Documentation

Note (11/24)

I have changed default Web socket library and that may arise build issues. If there are issues you may try to set USE_LIBWEBSOCKETS to OFF. (e.g. cmake -DUSE_LIBWEBSOCKETS=OFF ...). (I will remove this note later)

Install

Gempyre uses CMake. Therefore in general installing is just calling

  cmake my_cmake_folder -G Ninja
  cmake --build . 
  sudo cmake --install .

However there are some install scripts to help installing debug and release builds.

Linux

  • Run
    linux_install.sh
    

Mac OSX

  • Run
     osx_install.sh
    

Windows

  • Install git bash from https://gitforwindows.org/
  • Run git clone https://github.com/mmertama/Gempyre.git on git bash console.
MSVC
  • Install cmake https://cmake.org/download/ (let it to be added in path)
  • Install Visual Studio https://docs.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=vs-2019, and pick Desktop development with C++
  • Install Python (latest, yet tested mostly with 3.10, but 3.6 >= shall be ok) https://www.python.org/downloads/windows/
  • From Windows menu, Visual Studio: Open "x64 Native Tools Command Prompt for VS 2019" (later probably ok)
  • Run
     msvc_install.bat
    
MinGW
  • Make sure you are using the right MinGW shell (Msys minGW 64-bit - one with blue icon (Not brown or cyan :-))
  • See Instructions https://www.devdungeon.com/content/install-gcc-compiler-windows-msys2-cc
  • Ensure Ninja is installed pacman -S base-devel gcc vim cmake ninja
  • Run
    mingw_install.sh
    

Raspberry OS

  • Requires Rasberry OS Bullseye (older is ok, but you need more recent gcc in order to build C++17). Tested Raspberry Pi 3 and Raspberry Pi 4.
  • Quite late CMake is required, here are snap instructions.
  • Run
      pi@raspberrypi:~/Development/Gempyre ./raspberry_install.sh
  • When building on Raspberry, please pass -DRASPBERRY=1 for your cmake call. E.g.
       pi@raspberrypi:~/Development/Tilze/build $ cmake .. -DRASPBERRY=1

FAQ

Q: After installation you get: "WARNING: webview is not installed -> verification is not completed!", what is that?<br> A: Most likely python3 webview is not installed. See installation from pywebview. Please also make sure websockets python library is installed.

$ pip3 install pywebview && pip3 install websockets

The error is not fatal, but as a consequence the default UI is not drawn on its own window and it fallbacks to the default browser.

Q: How to use some HTML/JS/CSS feature for GUI from C++ that does not have a API?<br> A: Try Ui::eval(), it let you execute javascript in the gui context: e.g. Here I change a checkbox element so it fires a change event.

ui.eval("document.getElementById(\"" + check_box.id() + "\").click();");

To be clear, the checkbox change works:

Gempyre::Element(ui, "check_box_id").subscribe(Gempyre::Event::CHANGE, [&](const auto& e) {
    is_on = Gempyre::Event::has_true(e.properties, "checked");

Q: Why Canvas drawings seems to happen in random order?<br> A: Canvas drawing is highly asynchronous operation and subsequent CanvasElement::draw() operations may not get updated in the order you have called them. The solution is either make a single draw call where all items are updated once, or use CanvasElement::draw_completed() to wait until each draw has happen. CanvasElement::draw_completed() should be used for animations (or game like frequent updates) instead of timers for updating the graphics. Like this example

Q: Why Gempyre::Bitmap merge is not working?<br> A: You are likely merge an uninitialized bitmap. Gempyre::Bitmap(width, height) or Gempyre::Bitmap::create(width, height) does not initialize bitmap data, therefore it's alpha channel can be zero and bitmap is not drawn. To initialize the bitmap, use Gempyre::Bitmap::Bitmap(0, 0, width, height, Gempyre::Color::White), or draw a rectangle to fill the Bitmap, after the construction.

Q: How to scale Gempyre::Bitmap?<br> A: You can use browser's bitmap scaling by applying the bitmap as image and then using Gempyre::FrameComposer for draw. Look the following snippet:


// name the image
const auto image_key = "/my_image.png";

// I define a lambda for drawing to avoid copy-paste. texture_images maps image names and ids.
const auto texture_draw = [&ui, &texture_images, image_key, clip, rect]() {
  Gempyre::CanvasElement compose(ui, COMPOSE_CANVAS);
  Gempyre::FrameComposer fc;
  const auto id = texture_images[image_key];
  fc.draw_image(id, clip, target);
  compose.draw(fc);
};

 // test if image is already loaded
 const auto res = ui.resource(image_key);
    if(!res) {
      const auto png = bmp.png_image();  // bmp is the image we want to scale - but we make a png out of it
      if(ui.add_data(image_key, png)) {  // load the image
        const auto id = compose.add_image(image_key, [texture_draw](auto){
          texture_draw();                // draw when loaded, too early request wont draw anything
        });
        texture_images.emplace(image_key, id);    
      }
    } else {
      assert(ui.available(texture_images[image_key]));
      texture_draw();
    }

Q: How to do multiple Gempyre::FrameComposer in a single draw? My second draw is not visible<br> A: Do you call erase? See CanvasElement::draw_completed above. You may also try to call your drawn in a Ui::after` timer with 0ms delay, that should ensure the correct drawing order.

Q: Why my dynamic HTML <select> does not work with numbers?<br> A: The UI select uses strings, and hence the values has to be quoted strings.

  <select id="show_tags" disabled></select>  

   Gempyre::Element show_tags(ui, "show_tags");
   show_tags.remove_attribute("disabled");  // remove disabled
   // dynamical add items numerical keys
   for(const int value : tag_keys) {
        Gempyre::Element opt{ui, "option", show_tags};
        const auto value = std::to_string(value);   // number as a string
        opt.set_attribute("value", value); // In pre 1.8.6: GempyreUtils::qq(value), the numerical values had to be quoted, otherwise JS interpreted them as numbers!
        opt.set_attribute("name", "tag_option");
        opt.set_html(value);
    }

Q: I want to use Python window to have nice window and get file dialogs. But I do not get working in MacOS. A: The latest MacOS wish your run your Python in virtual environment. Look venv. As in any environment you may need to install pywebview and websockets. For example in venv shell call:

$ pip install pywebview websockets

However I noted that pywebview may not get successfully installed, and hence a link must be called, for example (please verify your python and pywebview versions):

$ ln -s ./venv/lib/python3.12/site-packages/pywebview-5.1.dist-info ./venv/lib/python3.12/site-packages/pywebview

Q: How to handle remove UI elements? A: There is Element::remove() that removes an element from UI and cleans up associated element handlers. However the element can be removed other ways, e.g. removing parent item or parent element calling Element::set_html that effectively wipes all child elements. You can detect that using Element::subscribe(Event::REMOVED). Please note that if element has any subscribed events, and if the element is expected to be remove othwerwise than Element::remove(); Event::REMOVED should be subscribed and call Element::remove() to exp

View on GitHub
GitHub Stars45
CategoryDevelopment
Updated10d ago
Forks3

Languages

C++

Security Score

90/100

Audited on Mar 28, 2026

No findings