![]() |
ImFusion SDK 4.3
|
With SDK version 4.0 we introduced the new ImFusionGUI component to provide a platform-independent abstraction layer for interactive GUI applications. Previously, our visualization stack relied on Qt for input event handling and embedding into a OpenGL-enabled display surface.
ImFusionGUI was designed to mostly follow the established display and view architecture and provide generic types for input events that can be used with all major GUI platform toolkits. However, in several instances we decided to improve the architecture to make it simpler and easier to maintain so that there is not always a 1-1 mapping between the old and the new API. Please follow this document to get detailed information on what has changed.
The old architecture was using QEvent
for representing user input events and handler functions usually exhibit a signature in the form bool sceneEvent(QEvent* event)
. The new architecture uses the GUI::InputEvent class instead and the canonical form for a handler function is GUI::EventResult handleInputEvent(const InputEvent& event)
.
An important change is that InputEvents are now immutable. Furthermore, event handlers shall never change any global GUI state (e.g. changing the mouse cursor, spawning a context menu). Instead, all feedback wrt. to the GUI is to be indicate through the GUI::EventResult struct that they return. Since InputEvents are often propagated to a series of cascading handlers until propagation shall stop the EventResult offers a combine() function to conveniently merge their payload.
The DataDisplayHandler interface exhibits a breaking change because the base interface type for views and displays has changed: The signature of all pure virtual member functions now expects a GUI::View instad of an InteractiveView and a GUI::DisplayBase instead of a DisplayWidgetMulti as parameters.
dynamic_cast
) to determine a view type and implement dispatch logic. Make sure to update those checks if you need to support the new GUI::SliceView and GUI::VolumeView classes. Significant architectural changes were made to the successors of DisplayWidget and DisplayWidgetMulti. Not only do they no longer depend on any Qt classes but their extensive set of functionality and responsibilities was split into multiple dedicated classes for a cleaner separation of concerns and improved reusability:
The new equivalent of the old InteractiveView is the GUI::View base class. Except for some general cleanup and renaming of some of the member functions the architecture and design has remained the same.
Use GUI::ViewOverlay as base class for view overlays. The general architecture is still the same except for:
handleInputEvent()
member function.Almost all InteractiveOverlays have been migrated to the new architecture. The class name remained the same except for dropping the Interactive
prefix and being moved to the ImFusion::GUI
namespace instead. For some overlays the original InteractiveOverlay variant was kept as a temporary deprecation layer.
Use GUI::ViewObject as base class for interactive scene objects to be rendered inside a view. The general architecture is mostly the same except for:
handleInputEvent()
member function to be overridden. Use the GUI::TypedViewObject instead if you need better composability and want to reuse a single GUI::ViewObject::EventHandler type for multiple view objects.The ImFusion::GUI component now uses consistently OpenGL coordinates (the same coordinate system as the underlying GlViews etc.), which means that the origin is in the lower-left corner of the viewport. This applies to all interfaces such as GUI::DisplayBase, GUI::View, GUI::ViewOverlay, and GUI::InputEvent.
Previously, DisplayWidget and InteractiveView were using Qt coordinate system where the origin is in the upper-left corner requiring a flip along the Y axis whenever one needed to convert to and from the coorindate system of the underlying renderers.
The new ImFusionGUI component was designed carefully to be interchangeable with the old framework to allow for a fluent transition during migration. This means that except for very few cases you can use classes inheriting from the new interfaces inside an old InteractiveView, as well as use classes still based on the old API inside the new API.
We designed a special compatibility layer of "adapters" for use cases where a component outside the GUI framework shall be able to work with both the old DisplayWidgetMulti-based framework and with the new GUI::RadiologyDisplay-based framework (e.g. Controllers). These adapters mimic the interface of the old framework and forward the calls to the corresponding instance of either the old or the new framework that they wrap. This enables you to implement a transition period where your existing code supports both frameworks at the same time.
For instance, existing code that expects a DisplayWidgetMulti-style API can use the DisplayWidgetMultiAdapter to transparently forward calls to either an actual DisplayWidgetMulti (in which case the calls are simply forwarded) or a GUI::RadiologyDisplay (in which case the corresponding new API is used). There are also the InteractiveViewAdapter, ImageView2DAdapter, ImageView3DAdapter, and ViewGroupAdapter classes that implement the same behavior for their corresponding classes.
false
, comparison to nullptr
will be true
, and you must not call any of its other member functions.