Qt-jambi-interest Archive, August 2006
Enums in Qt Jambi, Feedback wanted
Message 1 in thread
Hi guys,
We've been playing a bit with how to do enums recently and have reached
a prelimiary decision on how to do enums in Qt Jambi. A number of code
snips are attached to this mail with some comments to document the
primary use cases. We would like to known what you think of these
approaches.
The problems we aim to solve are these:
* Qt does in some cases use enums values that are not declared in the
enum declaration. Examples are QEvent.Type where users can define their
own event types. This is not possible with Java enums. We'll call these
extensible enums.
* Qt uses enums as flags (e.g. predefined values) encapsulate these
in a template type QFlags<T> type which makes it possible to do compile
time type checking of bitmasks and flags.
* We would like to provide a solution where we use Java enums for both
bitmasks and enums, extensible and non extensible. We want to be able to
use flags as they are used in Qt/C++, except for the operator
overloading. e.g. "flags &= ~mask" in C++ becomes "flags.clear(mask)" in
Java. And that this all works in a statically verifiable way.
In the attached code we focus on the use patterns that you guys will hit
while coding Qt Jambi. If you want to look at our actual solution, you
can see it in the next tech preview if we decide to go for it.
Thanks in advance for any feedback you may have.
The Qt Jambi Development Team
/* Normal enums, like Qt.BrushStyle. In this case QBrush()
takes an enum like this: QBrush(Qt.BrushStyle style). The
QBrush.style() function returns an enum of type
Qt.BrushStyle
*/
QBrush b = new QBrush(Qt.BrushStyle.CrossPattern);
switch (b.style()) {
case HorPattern: /* ... */ break;
case VerPattern: /* ... */ break;
case CrossPattern: /* ... */ break;
/* etc */
}
/* Extensible enums, like QEvent.Type. Similar to the case
above QEvent() takes an enum, and QEvent.type() returns an
enum.
*/
QEvent e = new QEvent(QEvent.Type.MousePressed);
switch (e.type()) {
case MousePressed: /* ... */ break;
case MouseReleased: /* ... */ break;
case MouseMoved: /* ... */ break;
/* etc */
}
/* Creating a custom event, done using the function resolve. All Qt
* enums will have this function.
*/
QEvent.Type customEventType1 = QEvent.Type.resolve(EVENT_ID_1);
QEvent.Type customEventType2 = QEvent.Type.resolve(EVENT_ID_2);
QEvent e1 = new QEvent(customEventType1);
QEvent e2 = new QEvent(customEventType1);
/* checking the custom event can be done using a switch like this: */
switch (event.type()) {
case MousePressed: /* ... */ break;
case MouseRelease: /* ... */ break;
case MouseMoved: /* ... */ break;
case CustomEvent:
switch (event.type().value()) {
case EVENT_ID_1: /* ... */ break;
case EVENT_ID_2: /* ... */ break;
}
break;
}
/* Or by checking for identity using an if statement, like shown
below. Multiple calls to resolve will return the same object so
both == and equals() can be used for matching.
*/
if (e.type() == QEvent.Type.MousePressed) { ... }
// Using an available QEvent.Type instance
if (e.type() == customEventType1) { ... }
if (e.type().equals(customEventType1)) { ... }
// Resolving for this comparison.
if (e.type() == QEvent.Type.resolve(EVENT_ID_2)) { ... }
if (e.type().equals(QEvent.Type.resolve(EVENT_ID_2))) { ... }
/* This also makes it possible to do type safe bit flags. This is done
* using the generics based base class QFlags<T> which is subclassed
* for each flags type. For QPainter.RenderHint with its QFlags
* version QPainter.RenderHints this looks like this:
*/
QPainter.RenderHints h1 = new QPainter.RenderHints();
h1.set(QPainter.RenderHint.SmoothPixmapTransform);
painter.setRenderHints(h1);
/* It will also be possible to construct hings using the constructor
and setting one set of flags on another set of flags. */
QPainter.RenderHints h2 = new QPainter.RenderHints(QPainter.RenderHint.Antialiasing);
h2.set(h1);
/* For setting multiple values we would do like this */
QPainter.RenderHints h3 = new QPainter.RenderHints(QPainter.RenderHint.Antialiasing,
QPainter.RenderHint.SmoothPixmapTransform);
h2.clear(QPainter.RenderHint.Antialiasing, QPainter.RenderHint.SmoothPixmapTransform);
h2.set(QPainter.RenderHint.Antialiasing, QPainter.RenderHint.SmoothPixmapTransform);