Trolltech Home | Qt-jambi-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 1

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);