Last month, I discovered the software application I wrote atop FLTK would not render text at the proper size on 4K resolution monitors. The version of FLTK I used was designed for 1080p monitors and earlier. During the last 4 years, I looked at using C++ code libraries to build GUI applications. I came across numerous code libraries that would provide a means to produce a GUI in C++, but I had to try them out first to see if they would be a good fit. Two of the most popular ones, Qt and wxWidgets, I studied in-depth before I decided not to use them at all.
Several libraries seemed promising. I started with Win32 but that was not cross-platform. I looked at Allegro but decided it was not productive enough. SFML was a little more productive but had too many dependencies. Eventually, I settled on FLTK. The great thing about FLTK was it was nimble, compact, and fast to set up and deploy and required very little to get up and running. I built an application using FLTK and was satisfied with the result until I ran it on a system with a 4K monitor.
Reconsidering the results of using FLTK meant going back to the drawing board. Years passed since I last reviewed a multitude of code libraries and frameworks. I knew that I could get a thorough implementation of the software using Qt or wxWidgets as they were mature and feature complete solutions. I am just a tad on the bleeding edge in terms of core compilers, C++ language version, and depth of control I would prefer in the software and those toolkits are not designed to keep pace with that. I have other reasons not to prefer those toolkits. I began to consider Allegro again.
One thing I wanted that FLTK delivered was productive, high-level widgets that I could declare in code and just use. FLTK already has things like buttons, scroll bars, list boxes and such that I could just use and link to data. Using pre-built widgets such as you have in frameworks like .NET, Java, and HTML seemed like a productive way to go. I would gain the use of code I didn’t have to write. That point of view had a flaw.
As of 2016, code libraries such as Allegro and SFML do not have widgets. When using them as your primary graphics definition tool, you have to create any widgets you need from scratch. It was my hope over the last 4 years to avoid that and reap the benefits of productivity. I understood that if I made my own widgets, I would have more control and a greater ability to adapt to changes in technology and hardware. I also knew in the back of my mind that if I was wrong about using a high-level, productive framework like FLTK or something similar, that I would probably have to write the application-level interactive graphics solution from scratch.
October 2016 came around and it quickly became apparent that to support the latest compilers, C++ standards, display resolutions, and other aspects of an operating environment writing from scratch using libraries limits you less than assembling widgets using third-party frameworks. I still recommend widget frameworks for IT departments, but for true world software, even for personal use, I recommend going with code from scratch. Even with the hassles as the issues will be far less than waiting 6-months to a year or more for a framework to get updated.
C++ GUI using Allegro 5 Graphics, dlib Geometry, and GCC 6
One of the most promising aspects of the Allegro 5 Graphics Library is are high-level drawing routines. The great thing about that is that is very productive if you are comfortable with geometry. Since that was one of my favorite areas of mathematics, I was pleased to see the presence of such high level routines in Allegro. It sped up my definition of lines for the widgets I needed to create.
Drawing the squares and other angles needed was fairly straightforward. What was unclear was the interaction needed to achieve the appearance of movement across a geometric plane. My concern was the speed of the operations to detect mouse movements within a certain area. I needed fast algorithms to achieve this goal. That is where the dlib library becomes useful.
Before I decided to use dlib, I had defined my own geometric primitives. As I got further into the new solution, I realized I was writing too much code and was going too in-depth into areas that had less to do with the application and more with the mechanics of geometric translation. I decided to replace the geometric primitives I had defined with those from the dlib library. Once I did that, it actually became easier to visualize the high-level models I needed to create to produce a more algorithmic process to convert from mouse interactions to movement of lines of text on the screen.
In the past, I’ve used both GCC and Clang at the same time to make sure I was qualifying the code from the perspective of two compilers. This time, I decided to stay with GCC to speed up my code iterations a bit. I plan on exercising the code through Clang at some point, but for now, the code has been vetted only through GCC. I am pleased with the results so far with an executable that is 5.7 MB in size with a debug build.
C++ GUI at 4K Resolution
The series of screen shots that follow show the example application output to a monitor at 4K resolution. Even though I am on Linux and using open source technology, I have to thank Microsoft for the font scaling algorithm. They have a web page where they describe their method for font scaling. The web page does not show actual code for font scaling, but I translated the textual description to a formula. After a few revisions, the formula results in font scaling that appears to work well at different display resolutions.
Screen shot 1 shows the full window with example, auto-generated text. I auto-generated 100 lines of text. I wanted enough lines of text that I knew would not fit into any of the graphical regions I setup. I have 3 graphical regions and with truncated text, the conditions are such that I could examine both the size of lines of text and see how well scroll bar functionality operated.