25 - 9 - 2020 - Expert blogs

Gempyre UI Framework

Every application has a UI, and picking the most suitable framework is crucial. Upon discussing the most suitable for each need, an idea emerged of another kind of approach: Gempyre 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 into use.

Software development

Some time ago, I had a chit chat about C++ UI frameworks, especially about lightweight alternatives to Qt which is a dominant choice for platform independent application development. Qt has a lot of features besides just a UI and it is a fat layer on top of C++. I was considering something simpler, less complex and more approachable, just focus on UI. I found some frameworks, but surprisingly few ─ and even fewer that are platform agnostic and support modern C++.

By digging out those I started to think about a framework from a slightly different angle: traditionally, you have a window and a set of widgets. The programmer creates a window (or windows) and places widgets to compose a user interface. The widgets implement buttons, dialogs, menus, text areas, basically all visible or functional elements.

Each of these widgets implements their own APIs that let programmers use and affect their behavior and outlook. Even the most simple UI framework may have 20 widgets, and each of them averages 20 method calls, which makes 400 methods to master in order to use the framework. Yet more complex frameworks like Qt or wxWidgets have thousands if not tens of thousands of API calls. Therefore I crafted Gempyre that throws away widgets all together.

Gempyre

For Gempyre, my approach was to use a web browser as a UI framework. Gempyre itself does not provide widgets and layout controls. The UI is supposed to be constructed separately as Web pages using Javascript, CSS, and HTML. Then that separated UI structure is accessed and controlled from C++ code. I avoided reinventing the widgets by delegating UI creation to the vast pool of common, de-facto, standard web technologies.

Gempyre library provides an interface to interact with the UI – the API is only a few dozen calls. This architecture naturally supports the MVC model: The computational part can be implemented using C/C++ engine, and then UI can benefit from rapid UI development with Web tools. Gempyre combines the power of C++ with myriad options of front end development tools, sources, documents and frameworks that are only available for Web Developers.

Gempyre is multiplatform; it is built using CMake and written using C++17 (tested OSX (CLang), Ubuntu (gcc), and Windows 10 (MSVC 19) ). The Gempyre framework can be downloaded from Github under MIT license. The Android support is implemented as Gempyre-Android - it is a wizard that creates you a running Android application skeleton using Gempyre.

Gempyre is implemented using C++, but for smoother coding, there is a Gempyre-Python Python wrapper available. It is a breeze for rapid UI development, especially compared to tkinter.

Hello world

As an example, here is a simple Gempyre application with a single button. The UI is written using HTML; please note the line is required for every Gempyre application. The HTML widgets are accessed by their HTML element ids from the C++.

...

And then we have a main.cpp. I discuss here every line by line. At first, gempyre.h is included so it can be used.

#include <gempyre.h>

Within Gempyre you normally build in the HTML and other resources, to compose a single file executable. It is preferred that Gempyre is statically linked in, thus the application is just a single file. Therefore distributing and executing Gempyre applications shall be very easy: just run it! There are no runtimes to install nor DLLs to be dependent on; just a single binary executable.

The resource composing is done in CMakeLists.txt (single line), yet here the generated header is included, it contains a ‘Hellohtml’ std::string object that will be passed then to the Gempyre::Ui constructor.

#include "hello_resources.h"

int main(int /*argc*/, char** /*argv*/) {

In the constructor, you provide a mapping between file names and generated data and the HTML page that will be shown.

`` Gempyre::Ui ui({ {"/hello.html", Hellohtml} }, "hello.html");

HTML elements are represented by Gempyre::Element. The element constructor takes a HTML id to refer to the corresponding element in the UI. Here we refer to the text area and button as defined in the HTML code above. The Gempyre::Element represents any of the HTML elements. It's only inherited class is Gempyre::CanvasElement that implements specific graphics functionalities.

Gempyre::Element text(ui, "content");

Gempyre::Element button(ui, "startbutton");

The Gempyre API provides a set of methods to get and set HTML content, values, and attributes. Here we just use setHTML to apply a given string as an element HTML content.

button.setHTML("Hello?");

The subscribe method listens for element events, and when the button is "clicked" a given function is executed.

button.subscribe("click", [&text]() {

text.setHTML("Hello World!");

});

The Gempyre::Ui::run starts an event loop. In this example, the system default web browser is opened, and the UI is executed on tab (there are more alternatives to have a system looking application) and the application is waiting for the button to be pressed or the browser window to be closed.

ui.run();

return 0;

}

Markus Mertama
writer

Markus Mertama

Senior Software Developer, Insta Advance

Share article

Stay on top of the industry trends and subscribe to our newsletter

The most important news, inspiring articles, and up-to-date insights from our experts across various industries and information about our upcoming events.

Accept the terms and conditions. We handle your information responsibly.
Please review our privacy policy.