This page describes the first cleanup pass that occurred on the KWWidgets source tree during the first semester 2005 at Kitware. This roadmap was intended to document the steps involved in turning the old Widgets repository into an independent project.
- [DONE] Remove dependencies on ParaView
- [DONE] Remove dependencies on VolView (and other Kitware internal projects)
- [DONE] Remove dependencies on KWCommon
- [DONE] Remove or reduce the dependencies on VTK
- [DONE] Separate the core widgets from the composite widgets
- [DONE] Make sure the Widgets tree can build as a standalone project and create examples
Dependencies on ParaView
All items DONE
- [DONE:Seb:4/1/2005] Move the "trace code" down to ParaView. The tracing framework is only used in ParaView; the code is spread and sometimes duplicated between vtkKWObject, vtkKWWidget and vtkKWApplication. Most UI classes in ParaView inherit from vtkKWObject or vtkKWWidget. Let's move the tracing members and factorize the code into a single vtkPVTraceHelper class, then create a vtkPVTracedWidget (subclass of vvtkKWWidget) that will hold an instance of vtkPVTraceHelper. If a given ParaView class can not be subclasses from vtkPVTracedWidget, one can still add a single vtkPVTraceHelper instance to the code; practically, this happens only in a few classes, vtkPVCornerAnnotationEditor, vtkPVTextProperty, vtkPVTimeLine, and vtkPVWindow. Significant work.
- [DONE:Berk] Move the whole vtkKWComposite, (vtkKWActorComposite, vtkKWGenericComposite) and vtkKWView framework down to ParaView. It is used only in ParaView and is source of many maintenance pains. A different model is used in applications like VolView, or VisualJournal, closer to a MVC (Model View Controller) design (see the vtkKWRenderWidget class and subclasses and the vtkKWUserInterfacePanel framework).
- [DONE:Eric Stanton] Move the Lookmarks back to ParaView.
Dependencies on VolView
All items DONE
- [DONE:3/9/05:Seb] Move the VolView XML reader/writer from GUI/Widgets/XML to GUI/WidgetsPro/XML.
Dependencies on KWCommon
All items DONE
- [DONE:3/25/05:Seb] Replace the old VTK containers by STL containers. The old containers in KWCommon are: vtkAbstractIterator, vtkAbstractList, vtkAbstractMap, vtkArrayMap, vtkArrayMapIterator, vtkContainer, vtkHashMap, vtkHashMapIterator, vtkLinkedList, vtkLinkedListIterator, vtkQueue, vtkQueueIterator, vtkVector, vtkVectorIterator. They are used in KWWidgets by vtkKWEventMap, vtkKWToolbar, vtkKWMaterialPropertyWidget, vtkKWNotebook, vtkKWToolbarSet, vtkKWUserInterfaceManager, vtkKWUserInterfaceNotebookManager, vtkKWWindow, vtkKWWidget (for Drag&Drop), and a whole array of "set of objects" that follow the same design: vtkKWCheckButtonSet, vtkKWEntrySet, vtkKWLabeledLabelSet, vtkKWPushButtonSet, vtkKWRadioButtonSet, vtkKWScaleSet. Significant amount work.
- [DONE:3/10/05:Seb] Move the KWCommon corner annotation class vtkCornerAnnotation to VTK's Hybrid/ package. This class is used in KWWidgets by vtkKWCornerAnnotation (a GUI to edit a corner annotation), vtkKWRenderWidget, and the corresponding XML Reader/Writer in the XML/ subdir.
- [DONE:3/11/05:Seb] Replace the calls to the KWCommon platform independent directory handling class vtkKWDirectoryUtilities with calls to the KWSys framework now included in VTK. This directory handling class is used in KWWidgets by vtkKWApplication, vtkKWLoadSaveButton and vtkKWTkUtilities. Get rid of vtkKWDirectoryUtilities.
- [DONE:3/9/05:Seb] Move the event enumeration class vtkKWEvent from KWCommon to KWWidgets. This class is used all over the place to invoke events, but is actually not used in KWCommon itself. It is used in KWCommonPro by vtkKWEventMap and vtkKWVolumeRayCastHelper, vtkKWVolumeRayCastMapper, vtkKWVolumeTextureMapper3D ; let's move vtkKWEventMap to KWWidgets, since it is a useful GUI class anyway, and move the small set of events used by the volume mapper classes back up to VTK's vtkCommand. Note that vtkKWEvent lists event that are used in PV, VV, and other projects, at some point a solution should be found to move them out into their own vtkVVEvent, vtkPVEvent, maybe by numbering them starting from 10000, 20000, etc.
- [DONE:3/11/05:Seb] Move the KWCommon histogram classes vtkKWHistogram, vtkKWHistogramSet to KWWidgets. They are used in KWWidgets by vtkKWColorTransferFunctionEditor, vtkKWParameterValueFunctionEditor, vtkKWVolumePropertyWidget.
- [DONE:3/11/05:Seb] Move the KWCommon icons class vtkKWIcon and the corresponding Resources/ subdir to KWWidgets. This class is used all over the place to use default icons. This is definitely a GUI class that probably should have been in KWWidgets in the first place.
- [DONE:3/11/05:Seb] Dispatch the additional KWCommon math functions in vtkKWMath to VTK's vtkMath, vtkDataArray, vtkPiecewiseFunction, vtkColorTransferFunction. This class is used in KWWidgets by vtkKWVolumePropertyWidget as well as vtkKWHistogram in KWCommon.
- [DONE:3/10/05:Seb] Move the KWCommon registery utilities class vtkKWRegisteryUtilities, vtkKWUNIXRegisteryUtilities, vtkKWWin32RegisteryUtilities to KWWidgets.
- [DONE:3/21/05:Seb] Remove the KWCommon serialization helper class vtkKWSerializer from the source tree. It is not used anymore, die code die.
- [Done:3/11/05:Seb] Remove the KWCommon string manipulations class vtkString and use calls to the KWSys framework now included in VTK instead. This class is used in KWWidget by +12 files, mainly to call ::Duplicate() and ::Length(), but also to use non-trivial functions like ::Crop, ::ToLower, etc. Let's move these methods to KWSys and get rid of vtkString.
The following KWCommon classes are not used anymore in KWWidgets:
- Various movie writers: vtkAVIWriter, vtkKWGenericMovieWriter, vtkMPEG2Writer.
- Command-line arguments parser: vtkKWArguments.
- Statistics such as cpu and memory usage: vtkKWProcessStatistics.
- Execute process on remote computer: vtkKWRemoteExecute.
Dependencies on VTK
All items DONE
Two solutions are considered. A partial removal that would leave a dependency to VTK's Common Kit, i.e. a dependency to the core vtkObject class, or a complete removal of the dependencies on VTK. The former has been chosen.
Try to link KWWidgets to vtkCommon only, check the failing dependencies on VTK and resolve them:
- [DONE:4/5/05:Seb] The vtkPNGReader class in VTK is used in KWWidgets to load resources, icons, splashscreens, etc. Let's add basic PNG reading capabilities to a vtkKWResourceUtilities class. We can link to VTK's libpng, since it is part of VTK's Utilities and is always built.
- [DONE:4/6/05:Seb] The zlib library is used in vtkKWIcon to decompress resources. We can link to VTK's zlib, since it is part of VTK's Utilities and is always built.
- [DONE:4/7/05:Seb] The Base64 routines in VTK's IO Kit vtkBase64Utilities are used for coding/encoding resources in KWWidgets, let's use the one in KWSys::Base64 instead, which is part of VTK's Utilities and is always built.
- [DONE:4/5/05:Seb] A copy of VTK's Wrapping/Tcl/vtktcl.c is replicated in several projects at different locations. Despite its name, that copy does not have the same contents, since it is only initializing VTK's Common Tcl Kit. This is used by ParaView and VolView, which do not Tcl-wrap the whole VTK anymore. KWWidget is and depends on VTK's Common, hence the init of vtkcommon. The VTK_TCL_HOME var is hacked to help finding this alternate vtktcl.c. Since KWWidget is being cleaned-up and will depend only on VTK's Common, move the contents of vtktcl.c to vtkKWApplication's init method.
- [DONE:4/15/05:Seb] Remove the vtkKWWindowCollection class, specialization of vtkCollection, and use STL instead.
- [DONE:4/15/05:Seb] Replace vtkstd:: with kwsys_stl::
- [DONE:Seb] Remove the vtkKWWidgetCollection class, specialization of vtkCollection, use STL instead.
Removing the dependencies to VTK completely involves duplicating code from vtkObject and creating a similar new superclass (say, vtkKWObjectBase). Of course, once you pull off vtkObject, more than a dozen of other files and classes have to be considered, eventually duplicated and/or simplified:
- vtkWin32Header.h: only a subset is needed (decl specs), check for the meaning of VTK_IN_VTK, __VTK_SYSTEM_INCLUDES__INSIDE, etc.
- vtkSystemIncludes.h: only a subset is needed
- vtkIOStream.h: Brad's suggestion, use kwsys_ios::ostream, etc., i.e. change *all* signatures from &ostream to &kwsys_stl::ostream.
- vtkIndent.h: why not
- vtkObjectFactory.h: the factory framework, which requires a good bunch of other classes too: vtkCriticalSection.h, vtkDirectory.h, vtkDynamicLoader.h, vtkObjectFactoryCollection.h (vtkCollection.h), vtkOverrideInformation.h, vtkOverrideInformationCollection.h, vtkVersion.h. Factories are not used that much in VTK anymore, so this whole part could be yanked.
- vtkObjectBase.h: brings vtkGarbageCollector.h (vtkGarbageCollectorManager.h), vtkDebugLeak.h (vtkDebugLeaksManager). Pretty much required.
- vtkObject.h: brings vtkCommand.h ; GetMTime() / Modified() (vtkTimeStamp.h): if we have our one timestamp, we won't be able to compare timestamps from the KWWidget library vs. timestamps from the VTK library (each one has its own static unique increasing timestamp). This should not be too problematic though.
- vtkCommand.h: the whole command/observer framework, etc. Required to implement callbacks on UI elements. Note that vtkKWEvent uses vtkCommand for GetStringFromEventId(), GetEventIdFromString(), i.e. if the event/string is not found in vtkKWEvent, lookup in vtkCommand. What will happen now that vtkKWEvent will be independent of VTK's vtkCommand ?
- vtkSetGet.h: only a subset is needed. Can we use #ifdef macroname to make sure we can include both vtkSetGet.h and vtkKWSetGet.h ? Brad suggested using different macro names, i.e. kwSetStringMacro instead of vtkSetStringMacro, but it would require a massive change to our while library and have people learn both syntaxes.
- VTK String, containers, collections: use KWSys instead, vtkstd::string => kwsys_stl::string, vtkstd::list => kwsys_stl::list, etc.
- Wrapping: VTK/CMakelists.txt: new wrappers have to be created. Check VTK_WRAP_TCL3_INIT_DIR, CMake/vtkWrapTcl.cmake ? vtkWrapTcl.c: ref to vtkObject, vtkObjectBase, etc.
- The conditions listed in the previous section "Partial Removal" apply too.
Headers so far:
- [DONE:Seb] Once the action items in this section are completed (either complete or partial removal), move all composite UI widgets that depend on VTK to VTK/GUISupport/KWWidgets (transfer function editors, color preset, corner annotation editor, header annotation editor, material property widget, render widget, scalar bar annotation). Check the "Core vs. Composite Widgets" section below. UPDATE: this is overkill, will make things more difficult to maintain... The KW cleanup was mainly done for NA-MIC/Slicer, which uses VTK extensively already.
- [Done:Steve Pieper] If Slicer is still using VTK 4.4, backport (#ifdef...) the code. UPDATE: Steve is already porting Slicer to 5.0, and was able to run KWWidgets.
Core Widgets vs. Composite Widgets
All items DONE
Create a simple separatation between core widgets and composite widgets. Core widgets are simple mapping of Tk widgets, like a scale widget (vtkKWScale), a checkbutton widget (vtkKWCheckButton), a frame (vtkKWFrame), etc. Composite widgets are complex widgets created by assembling core widgets or creating whole new UI elements (vtkKWParameterValueFunctionEditor, vtkKWExtent, etc.).
Right now, this separation does not exist, all widgets are subclasses of vtkKWWidget, but at the end of the day, some methods either do not make sense for complex widgets, or are shadowed by subclasses. Example: vtkKWWidget's GetBackgroundColor returns the Tk color of the widget background, but ends up returning the background color of the VTK viewport in the vtkKWRenderWidget's GetBackgroundColor subclass method.
Methods like SetCommand, GetType, HasConfigurationOption, SetImageOption could be either moved to vtkKWTkUtilities or to a vtkKWCoreWidget class, parent of all core widgets. Composite widget could inherit from vtkKWCompositeWidget. Methods common to both core and composite could be moved to vtkKWWidget. It is a matter re-shuffling/re-factoring some vtkKWWidget methods to the two new subclasses so that the overall signatures and documentation of subclasses make sense.
At the end of the day, a better control and separation of the core widgets could enable us to switch to a different underlying UI engine than Tk, or upgrade Tk to use the Tk future theme/tile engine.
|Helpers||Core Widgets||Composite Widgets||VTK Widgets|
Labeled widgets, sets of widgets
All items DONE
- [DONE:3/19/05:Seb] Simplify the labeled objects. The whole vtkKWLabeled* hierarchy holds more than 15 classes (!), we can certainly find an easier way to actually label any core widget without creating a separate class for each one. Since C++ templates can not be wrapped, let's use CMake configure_file command to generate subclasses automatically, following a simple C++ template. Significant work. Now documented automatically in the API's Auto-Generated Classes section.
- [DONE:3/19/05:Seb] In the same way, simplify the set of objects. The whole vtkKW*Set hierarchy holds more than 11 classes (!), we can certainly find an easier way to use/access a set of core/composite widgets without creating a separate class for each one. Since C++ templates can not be wrapped, let's use CMake configure_file command to generate subclasses automatically, following a simple C++ template. Note that vtkKWRadioButtonSet goes the extra-mile and make sure all radiobuttons are activated correctly within the set. Significant work. Now documented automatically in the API's Auto-Generated Classes section.
Other Clean ups
All items DONE
- [DONE:3/11/05:Seb] Move to a subdir: kwappicon, vtkbwidgets, vtkcombobox are all extra Tcl/Tk scripts that can be put in a subdir; developers and users do not need to know about them.
- [DONE:1/4/05:Seb] Rename vtkKWCornerAnnotation to vtkKWCornerAnnotationEditor (to avoid the confusion with VTK's vtkCornerAnnotation), vtkKWHeaderAnnotation to vtkKWHeaderAnnotationEditor (to avoid the confusion with vtkHeaderAnnotation), vtkKWListSelectOrder to vtkKWListBoxToListBoxSelectionEditor, vtkkWTextProperty to vtkKWTextPropertyEditor (to avoid the confusion with VTK's vtkTextProperty).
- [DONE:3/11/05:Seb] Remove KitwareLogo.h, since we always use a per-appplication logo anyway; bitmaps.h (useless); vtkKWOKCancelDialog, since its functionalities are in vtkKWMessageDialog already.
- [DONE:7/18/05:Seb] Check for duplicate functionalities between vtkKWPopupFrame* and vtkKWPushButtonWithMeny.
- [DONE:7/18/05:Seb] Move vtkKWBWidgets, which is actually not a UI object and does not even need to be a class, to Widgets/Utilities as a .cxx file only. Do not wrap.
- [DONE:3/20/05:Seb] Fix the whole SetLabel() vs. SetText() confusion. Some core widgets use SetLabel(const char*) or SetText(const char*), to set the same Tk option (-text). Some composite widgets use SetLabel(const char*), but on the other hand have a GetLabel() that returns... a vtkKWLabel ! Let's use SetText() everywhere in the core widgets, and SetLabelText() for all composite widgets that have an internal vtkKWLabel.
- [DONE:3/25/05:Seb] Move the Drag&Drop framework out of vtkKWWidget to a separate class vtkKWDragAndDropTargetSet.
- [DONE:3/24/05:Seb] Move the "Most Recent Files" framework out of vtkKWWindow to a separate class vtkKWMostRecentFilesManager.
- [DONE:3/24/05:Seb] Fix the "Registry" spelling (Registery -> Registry)
- [DONE:4/1/05:Seb] Rename vtkKWRegistryUtilities to vtkKWRegistryHelper. Let's stick to the same pattern: routines that need an instance are factorized into a "Helper", *static* routines that do not need an instance (and won't), are factorized into a "Utilities".
- [DONE:6/2/05:Seb] Fix the whole vtkKWFrame::GetFrame() issue; this is the only widget that requires a call to GetFrame()->GetWidgetName() instead of just GetWidgetName(). Remove the level of indirection: if you want a frame, use vtkKWFrame, subclass of vtkKWCoreWidget. If you want a scrollable frame, use a vtkKWFrameWithScrollbar, subclass of vtkKWCompositeWidget.
- [DONE:4/11/05:Seb] Move the vtkKWApplication's balloon code/ivars to a vtkKWBalloonHelpManager class, and add the corresponding instance to vtkKWApplication. Make sure this instance is lazy-allocated and lazy-created.
- [DONE:4/16/05:Seb] Create a toplevel class; many classes (vtkKWBalloonHelpManager, vtkKWDialog, vtkKWPopupButton, vtkKWScale, vtkKWSplashScreen, vtkKWTclInteractor, vtkKWThumbWheel, vtkKWWindow) create toplevels on their own and duplicate the code used to display/raise/iconify/focus the toplevel. Create a vtkKWTopLevel class and factorize all subclasses.
- [DONE:7/15/05:Seb] Create a more conventional "Dialog Settings" / "Preferences" modal dialog, instead of packing all the application settings in the left panel. This can be done easily by creating a new user-interface manager, vtkKWUserInterfaceManagerDialog: instead of displaying frames on top of each other in a notebook pane (say, "Interface Settings", "Toolbar Settings", "Application Area" for VV), we create a dialog with, on the left, a list of labels (say, "Interface Settings", "Toolbar Settings", "Application Area" for VV), and on the right, when you click on the label the left, the corresponding labeled frame. Wizard style. See Opera:Preferences:Advanced for example, or Eudora:Tools:Options, etc.
- [DONE:7/12/05:Seb] Collapse vtkKWOptionMenu and vtkKWMenuButton into a single class (named vtkKWMenuButton, even though vtkKWOptionMenu is the most complete one). The difference between the two is that vtkKWOptionMenu adds radiobutton commands by default, whereas vtkKWMenuButton adds commands. But both signature could co-exit, and since the vtkKWMenu object can be retrieved anyway, it does not really matter...
- [DONE:5/26/05:Seb] Create a vtkKWWindowBase class with all the vtkKWWindow code needed to display a simple window (i.e. menu + big frame + status bar). vtkKWWindow will be a subclass with the split frames, notebooks and user-interface managers.
- [DONE:5/26/05:Seb] Move GrabDialog out of vtkKWDialog to vtkKWTopLevel and have vtkKWDialog call vtkKWTopLevel::Display properly.
- [DONE:5/27/05:Seb] Fix the vtkKWProgressGauge height setting, it should expand automatically.
- [DONE:6/02/05:Seb] Make vtkKWApplication's DisplayHelpDialog method smarter, open CHM and HTML automatically.
- [DONE:6/04/05:Seb] Modify some ownership code (Register/Unregister) so that user interface panels and toolbars can be deleted immediately after addding them to the user interface manager and toolbar set (respectively). This makes clean up easier since the toolbar set and manager destructions are handled by the window already.
- [DONE:6/06/05:Seb] Fix the vtkKWSplitFrame orientation problem. Right now, Frame1 is on the left (or top), Frame2 is on the right (or bottom), but Frame2 behaviour in a vertical configuration should actually be the Frame1 behaviour in a horizontal configuration, i.e. should not resize on <Configure> events, but stay "fixed", so that panels/UI can be put there.
- [DONE:6/04/05:Seb] Remove all the Get*Color signature that takes 'int' parameters. We use 'double' in the VTK/KW realm.
- [DONE:6/16/05:Seb] Unify all the Create() method signatures. Some take extra Tk args, some do not. Some distribute the args to different internal widgets, some to the main ones. At the end of the day, a whole lot of Tk options are passed that way. We do not want to expose that. Remove any parameter to Create() and enforce the use of the C++ front-ends to the Tk options (for ex:, SetBackgroundColor instead of -bg, SetBorderWidth instead of -bd, etc.). This also make debugging Tk code easier. Lots of work on this one, pretty much every class has to be modified.
- [DONE:6/22/05:Seb] Remove all the "this->CommandFunction = vtkKWFoobarCommand(ClientData...)" code. It is obsolete, the wrapper got smarter some time ago.
- [DONE:7/20/05:Seb] Move the tablelist mega-widget that is bundled in Utilities/TclTk as part of PV or VV and used in vtkKWMultiColumnList to Widgets/Utilities.
- [DONE:8/1/05:Seb] Fix the vtkKWScale, it has grown out of control, using up to 7 internal sub-widgets to what should be a simple core widget. The SmartResize ivar adds ton of weird layout code. Clean the code, create a core vtkKWScale widget on top of the Tk 'scale' core widget, then a composite vtkKWScaleWithEntry, based on vtkKWScaleWithLabel, auto-generated subclass of vtkKWWidgetWithLabel. That way, we can use the common label positioning code. Make sure we support vertical scale.
- [DONE:8/4/05:Seb] Split vtkKWLabel into two core widgets. At the moment, it uses two different core Tk widgets under the hood, depending on an ivar, but changing that ivar forces the widget to be destroyed, a potentially very unstable situation. Some options are only relevant to one or the other core widget. Split the class into a vtkKWLabel (the core Tk 'label'), and vtkKWMessage (the core Tk 'message'), that is more suitable to long texts.
All items DONE
- [DONE:Seb] Create some examples of standalone UI apps in GUI/Widgets/Examples. Check examples section.
- [DONE:Seb] Create a "widget tour" sample. Check examples section.
- [DONE:Seb] Try as much as possible to write the same example in C++ and Tcl (Slicer UI is in Tcl).
- [DONE:Steve] Compile against the same version as Slicer's VTK (see Engineering:Project:Slicer3.0)