U++ Overview
Table of contents
2. Everything belongs somewhere
5. Dialog templates are C++ templates
1. Whetting your appetite
U++ promises radical reduction of code complexity of typical desktop applications. Let us start with a simple example – an application that displays the number of days between two dates. The number of days is refreshed as user types or edits dates into the input fields:
The application window layout is created using U++ visual designer:
The actual code for the application is as complex as this:
#include
#define LAYOUTFILE
#include
class Days : public WithDaysLayout
public:
typedef Days CLASSNAME;
Days();
};
Days::Days()
{
CtrlLayout(*this, “Days”);
date1 ^= date2 ^= [=] {
result = IsNull(date1) || IsNull(date2) ? “” :
Format(“There is %d day(s) between %` and %`”, abs(Date(~date1) – Date(~date2)), ~date1, ~date2);
};
}
GUI_APP_MAIN
{
Days().Run();
}
2. Everything belongs somewhere
In U++, most objects are bound to some logical scope. As a result, you will not see many new operators in code using U++ and almost no delete operators outside the implementation of containers.
That of course does not mean you are not allowed to use pointers, but it is good practice to use pointers just to point to things, never to manage heap resources. This also avoids all confusion regarding ownership of the underlying object, time of its deletion etc. If you need to manage data sets of variable size or polymorphic type, you should prefer using one of U++ containers.
Speaking about it, there are no shared smart pointers (like boost::shared_ptr) in U++ used to manage heap resources at interface level. They are not needed and considered bad practice.
In C++, this approach proves to be equally good or better than garbage collected languages like Java or C#. While those languages are able to provide automatic management of heap resources, U++ approach provides very deterministic automatic management of all resources.
3. U++ containers
One aspect of U++ is bringing a lot of criticism: U++ is not using much of standard C++ library. There are, however, serious reasons for this. STL, with its devastating requirement that each element stored in container has to have copy-constructor, makes standard containers somewhat hard to use in GUI development.
There is no such general requirement for U++ containers. Instead, U++ containers come in two flavors.
Vector flavor has Moveable requirement that allows very fast implementation for certain types (e.g., element insertion at arbitrary position of U++ Vector
Array flavor has no requirements for element types at all, at the price of somewhat lower performance.
As a result, in U++ you are for example allowed to create container of .GUI widgets that edits integer numbers ( Array
4. Who owns widgets?
One of the things we discovered over our countless experiments with C++ GUI is the fact that the GUI toolkit should not own widget objects. GUI objects should be always owned by the client, belonging to some scope of client code (everything belongs somewhere). GUI toolkit just references them, it neither creates them nor destroys them. Each widget object can play its GUI role in some context (like being visible in some window), but at the same time it is always a stand-alone entity with its set of attributes that can be modified or queried regardless of its current GUI status.
This has many serious implications. The most important is that U++ does not require widget objects to be allocated on the heap. That in turn allows us to arrange GUI dialog structure in a very effective way, instead of
struct MyDialog {
Option *option;
EditField *edit;
Button *ok;
};
we are using:
struct MyDialog {
Option option;
EditField edit;
Button ok;
};
Even more important, lifetime of these widgets does not depend on the life cycle of MyDialog GUI – MyDialog can be closed or not yet open, but attributes of widgets are accessible all the time.
5. Dialog templates are C++ templates
Now that we have laid down the foundations, it is time to introduce the coolest aspect of U++ GUI programming – layout templates:
If you visually design a layout (usually, but not limited to, the layout of a dialog box) using TheIDE’s Layout designer, this layout is in in your code reflected as a C++ template that derives from a widget-based class and declares all widgets as its member variables, and a matching function (InitLayout) that sets up the widget positions and their pre-d