Difference between revisions of "Slicer3:Interface Design and Usability"

From NAMIC Wiki
Jump to: navigation, search
m (Update from Wiki)
 
m (Update from Wiki)
Line 11: Line 11:
 
Design and engineer Slicer3 UI. Employ a user-centered approach and establish usability guidelines.
 
Design and engineer Slicer3 UI. Employ a user-centered approach and establish usability guidelines.
  
<br />
+
= Project reporting =
  
= Design and implementation sub-goals =
+
The scope of this effort is sorted into four categories: Engineering, UI design, Usability and Slicer3 branding. The subtasks of each category are itemized below and specific information about each category is located on the linked pages.
  
The scope of this effort divides into three categories: architecture, visual design, and usability.
+
=== UI Architecture & Engineering ===
  
'''Architecture & technical implementation'''
+
Tasks: (more detailed UI Architecture & Engineering information can be found [[Slicer3:UIEngineering|here]]).
  
* make final choice on while GUI toolkit to use (we are currently assuming to use Kitware's KWWidgets, though some discussion with Trolltech regarding the use of Qt under special licensing is ongoing...)
+
* design thin GUI layer, separate from the control logic and data model;
* decide how to separate the UI from the control logic and data model as neatly as possible;
 
 
* design a model for representing the UI and managing local events;
 
* design a model for representing the UI and managing local events;
 
* extend the model for handling remote events;
 
* extend the model for handling remote events;
 
* design means of mapping KWWidgets onto that model;
 
* design means of mapping KWWidgets onto that model;
 
* set priorities with Kitware involving extensions & modifications to KWWidgets;
 
* set priorities with Kitware involving extensions & modifications to KWWidgets;
* determine the api to application logic;
+
* determine the api to application logic, used by GUI and by scripts;
 +
* design set of base classes that give module developers an easy pattern to follow;
 +
* develop guidelines for slicer base developers and module developers;
 
* design mechanism for centrally specifying look & feel (and permitting overrides);
 
* design mechanism for centrally specifying look & feel (and permitting overrides);
  
'''Visual design & prototypes'''
+
=== UI Design & Prototypes ===
  
* design overall look to Slicer main app;
+
Tasks: (more detailed UI Design & Prototype information can be found [[Slicer3:UIDesign|here ]]).
 +
 
 +
* design overall look to Slicer3 application in keeping with core values;
 
* design look & feel applied to developer modules;
 
* design look & feel applied to developer modules;
 
* design KWWidgets class to specify custom widgets for Slicer main app & modules;
 
* design KWWidgets class to specify custom widgets for Slicer main app & modules;
 +
* implement Slicer3 Application GUI
 +
* design conventions for specifying global and module-specific keyboard accelerators;
 +
* specify and document global keyboard accelerators;
 
* iterate on prototype(s) and present them for comments and suggestions;
 
* iterate on prototype(s) and present them for comments and suggestions;
* develop and publish design guidelines;
 
* fully express Slicer3 brand: design logo, splash screen, style sheets for web presence;
 
  
'''Usability'''
+
=== Usability ===
 +
 
 +
Tasks: (more detailed Usability information can be found [[Slicer3:Usability|here ]]).
  
 
* determine which Slicer3 tools will require user studies and user testing;
 
* determine which Slicer3 tools will require user studies and user testing;
 
* develop mechanisms for user feedback on usability issues.
 
* develop mechanisms for user feedback on usability issues.
 
* interview core user community members to investigate general and domain-specific usability issues, user requirements, technical requirements.
 
* interview core user community members to investigate general and domain-specific usability issues, user requirements, technical requirements.
* consolidate what is learned for reference and use in design process
+
* consolidate and report what is learned for reference and use in design process
 
* test designs with members of the user community, analyze testing results & iterate
 
* test designs with members of the user community, analyze testing results & iterate
 +
* develop and publish design guidelines to support usability and software consistency.
  
Progress on each of these subgoals is/will be addressed below.
+
=== Slicer3 Brand ===
  
= Progress =
+
Tasks: (Slicer3 brand sketches can be found[[Slicer3:Slicer3Brand|here ]]).
  
* '''01/10/06''' Begin experimenting with KWWidgets:
+
* fully express Slicer3 brand: design logo, splash screen, style sheets for web presence;
** check out KWWidgets from cvs repository
 
** need VTK 5.0 or later, co from cvs with -r VTK-5-0
 
** use CMake 2.0 to build
 
* '''01/11/06''' Discussions on usability and user-centered design at NA-MIC AHM in SLC
 
* '''01/12/06''' Begin porting Ibrowser to KWWidgets as an experiment
 
* '''01/16/06''' Coarse draft of architecture for GUI layer.
 
* '''01/17/06''' Architecture meeting
 
* '''01/18,23''' Initial interviews with members of core user community
 
* '''01/24/06''' Architecture meeting
 
* '''01/30,2/3''' Initial interviews with members of core user community
 
* '''02/10/06''' Draft GUI classes and GUI example checked into svn
 
* '''02/13/06''' Working on sketches of main GUI layout
 
* '''02/23/06''' Visit to kitware for meeting and discussion
 
* '''02/24/06''' Refactored GUI base classes as per discussion
 
* '''02/26/06''' Redesigned sketches of main GUI layout after Kitware mtg
 
* '''03/19/06''' Making Slicer3 main window reflect layout prescribed by design
 
* '''03/28/06''' Refactored GUI base classes again to include GUI to data mediator
 
* '''03/29/06''' Working on incorporating framework for undo
 
 
 
[[Slicer3:Interface_Design|Return to TOC ]]
 
 
 
= Design process =
 
 
 
<br />
 
 
 
[[Slicer3:Interface_Design|Return to TOC ]]
 
 
 
<br />
 
 
 
== Proposed "multi-resolution" design process ==
 
 
 
* Define design goals
 
* Define core values interface and interaction should reflect
 
* Evaluate technology resources (below) and select tool suite.
 
* Based on experience with existing Slicer, Slicer developers needs and Slicer user needs, design coarse ''interaction framework'' for overall UI with all undesigned-but-accounted-for feature sets (like viewer, editor, control panels, status displays, etc.):
 
** define information architecture (driven by lists of Slicer components, rather than by concrete visual design)
 
** define application structure (bones for visual design)
 
** identify system behavior to satisfy broad requirements in general use contexts; identify appropriate design patterns that incorporate design goals and core values.
 
** define what kinds of actions a user can take (direct manipulation from GUI, scripting, keyboard shortcuts, macros, single-click webstart).
 
* Design coarse ''visual form'' of overall UI, with all undesigned-but-accounted-for feature sets: design variations on functional organization, layout and behavior based on coarse interaction framework, design goals and core values. Develop design appropriate for underlying GUI toolkit.
 
* Mock up, demo and discuss; get early feedback from users as time permits (the more the better) choose a coarsely prescriptive form with which subsequent design will conform [[Slicer3:Visualization_Prototype|(coarse visualization prototype)]].
 
* Develop draft of design guidelines to support consistency conformance.
 
* Design architecture of GUI Layer and its interface to application layer, informed by design of data model, chosen resources, and broadly defined user & technical requirements.
 
* Determine specific domains as our core user communities
 
* Focus on a first common-use component of Slicer (editing tool or scene graph browser) for core communities and assess needs for each core user community where tool is important;
 
** observe and interview users in their laboratories using tool
 
** model users and their existing or desired workflow;
 
** Define user and technical requirements for these feature sets;
 
* Establish interaction framework for these feature sets:
 
** identify a model for how these tools (and others will) fit within the coarse interaction framework;
 
** define information architecture;
 
** define tool physical structure;
 
** identify system behavior to satisfy requirements in important use contexts & identify appropriate design patterns that incorporate design goals and core values.
 
* Design specific visual form of UI for these tools: design functional organization and layout based on interaction framework, design goals and core values.
 
* Develop and evaluate prototypes with the user community, '''incorporating as much user-testing as possible'''. [[Slicer3:Visualization_Prototype|(visualization prototype)]].
 
* Refinement of behavior, form and content.
 
* Publish a recommended process for the user-centered development of custom slicer modules.
 
* Repeat design process with other Slicer components while continuing to develop the overall UI in a compatible manner.
 
* Implement, test and revise.
 
* Develop & disseminate Slicer3 brand, specs, defs, style guides.
 
 
 
== Slicer3 design goals ==
 
 
 
1. Shape the user’s understanding; enable a user to completely understand and effectively use the content being presented.
 
 
 
2. Enable a user to accomplish a principle task by following an appropriate and satisfying FLOW: a serial or iterative workflow, or an unfolding goal- or curiosity-driven exploration at an appropriate pace.
 
 
 
3. Because Slicer3 is an end-user application ''and'' an open-source software effort, also enhance and support the developer's experience.
 
 
 
== Core values ==
 
 
 
This is a working list of the core values the interface and interaction should reflect/support (please refine). These are not "specifications", but rather, think of them as concepts that our user communities would value highly and which would effectively and honestly distinguish the software. These are the concepts we'd like Slicer3 to strongly project:
 
 
 
* Simplicity
 
* Clarity
 
* Control & Precision
 
* Information-rich
 
* Open source & cross-platform
 
* Furthering scientific research
 
* Assisting treatment/therapy
 
* Advanced research ''showcase''
 
* Easily extensible
 
* Interactive & responsive
 
* Reliable
 
* Longterm viability
 
 
 
<br />
 
 
 
[[Slicer3:Interface_Design|Return to TOC ]]
 
 
 
<br />
 
 
 
= Architecture & technical implementation =
 
 
 
== Slicer3 GUI layer architecture ==
 
 
 
=== Architecture ===
 
 
 
Our goal is to create a thin GUI layer for Slicer3 whose architecture allows the flexible expression of interfaces that are appropriate for Slicer’s different use scenarios: an end-user application graphical user interface; script-driven batch processing and unit testing; and command-line style interaction for launching pipeline/grid processing, debugging during development, ''etc''.
 
 
 
Slicer2's GUI code is quite dense, mixed in with application control logic and data model. There is no way to separate the gui from the rest of the Slicer application. To meet our goal, the Slicer3 architecture will require a more thoughtful translation of existing modules' functionality, and won't be as simple as dropping in a new set of widgets.
 
 
 
The schematic below shows the Slicer3 GUI layer design and two paths between it and the application layer (which includes the logic layer as shown, and the data model): the VTK pipeline, and the GUI mediator.
 
 
 
<br />[[Image:GUIarch.gif|[[Image:GUIarch.gif| GUI connecting to application layer through mediator]]]]
 
 
 
<br /> The GUI mediator contains observers on the GUI elements, observers on the logic and observers on the data. An observed change to the transient state of any layer invokes a command that updates the transient state of the other layers through its API. This design isolates the application layers from GUI code, allowing them to be invoked by a script, without a graphical user interface, or with a completely different GUI.
 
 
 
The GUI's style will be designed to reflect Slicer3 brand. Developers will be encouraged to adhere to style guidelines to maintain a consistent look and feel across core and custom modules and to make Slicer3 easier to learn. The style will be defined in an external XML file, and parsed into the application at launch. Provisions to override the style will be included in case a developer requires the ability.
 
 
 
=== How to draft a Slicer module (MyModule) GUI class ===
 
 
 
First, note that the GUI base classes are likely to be refactored as Slicer develops, so if your existing module stops compiling, you can check back here to see what has changed.
 
 
 
To create a Module GUI that expresses its interface in Slicer's shared UIpanel, derive your class (vtkSlicerMyModuleGUI) from vtkSlicerModuleGUI. For a Module GUI that expresses its interface in a different panel of the Main Slicer Window, or in a toplevel widget, derive vtkSlicerMyModuleGUI from vtkSlicerComponentGUI instead. Your GUI class will inherit application logic and MRML pointers, an API for setting and observing them, and a framework for defining MRML, Logic and GUI callbacks from its parent class. Specific mediator methods, other logic and MRML node pointers, and methods for setting and observing them can be added to the module's class definition. Importantly, keep logic classes independent of the GUI to facilitate testing and command-line execution.
 
 
 
An early example to work from is the current placeholder for vtkSlicerVolumesGUI; define all the widgets you need within the class and create Get Macros for each of them. Define the methods you need from vtkSlicerComponentGUI, including BuildGUI(); in this method, you'll first add a page to the class's UIPanel (for now, only create one page). Different logical sections of your interface like "help" and "display" (which were located in separate notebook tabs in Slicer2) will be located in instances of the vtkKWFrameWithLabel widget, and packed into the UIPanel page. This approach produces a vertical stack of collapsable frames in the UIPanel instead of horizontally arrayed tabs.
 
 
 
Define the SetModuleLogic(), SetAndObserveModuleLogic(), SetMRMLNode(), and SetAndObserveMRMLNode() methods if you need to dynamically set a pointer to the module's logic class for the GUI to use, remove observers on an old logic pointer (if one exists) and add observers onto the new logic. Define the other methods you require from vtkSlicerComponentGUI base class, like: AddGUIObservers(), RemoveGUIObservers(), ProcessLogicEvents(), ProcessGUIEevents(), ProcessMRMLEvents(), Enter() and Exit(); and whatever else your module needs.
 
 
 
In AddGUIObservers, add an observer on each widget whose events you want to process. (You may need to define your own events.) When that event is observed, the ProcessGUIEvents() method is called via the GUICallbackCommand; define this class to propagate information from the GUI to logic and MRML. Though it is tempting, try not to use ProcessGUIEvents() to update the GUI state directly -- just modify the Logic state, and allow observers on the logic and subsequent processing in ProcessLogicEvents() and ProcessMRMLEvents() to bring that state change BACK into the GUI. (The draft version of vtkSlicerVolumeGUI breaks this rule because its sister Logic class isn't yet defined -- we'll build a better example as soon as we can!)
 
 
 
For now, to test your module, create a new instance of vtkSlicerMyModuleLogic and vtkSlicerMyModuleGUI in Slicer3.cxx, and follow the example of vtkSlicerVolumesGUI there for now.
 
 
 
=== GUI Base classes ===
 
 
 
GUI base classes to support this architecture have been derived from existing VTK and KWWidgets classes. An outline of these evolving GUI base classes (which contain the mediator functions) is given below:
 
 
 
<nowiki>
 
//--- SLICER STYLE CLASSES
 
vtkSlicerColor : vtkObject
 
 
vtkSlicerFont : vtkObject
 
 
vtkSlicerStyle : vtkObject
 
 
    vtkXMLParser *StyleParser;
 
    ApplyPresentation ( );
 
    WriteCascadingStyleSheet ( );
 
    ...
 
 
 
//--- SLICER APPLICATION CLASS
 
vtkSlicerApplication : vtkKWApplication
 
    vtkStyle *SlicerStyle
 
    // a collection of GUIs that express their
 
    // interface inside Slicer's main UIpanel.
 
    vtkSlicerGUICollection *ModuleGUICollection;
 
    AddGUI ( );
 
    CloseAllWindows ( );
 
    ConfigureApplication ( );
 
    StartApplication ( );
 
 
 
//--- COLLECTION of vtkSlicerModuleGUIs
 
// When a new Module GUI is created, it should
 
// be added to the application class's ModuleGUICollection
 
// using the AddGUI() method. This way the application
 
// can keep track of all the GUIs sharing Slicer3's main
 
// UIpanel.
 
vtkSlicerGUICollection : vtkCollection
 
    ...
 
 
 
//--- BASE CLASS FOR ALL MODULE GUI CLASSES
 
// contains gui and mediator functions,
 
// and pointers to application layer. We've gone
 
// back and forth about whether to assign static
 
// pointers to MRML here, and put observers on
 
// those; currently those resources are again
 
// included in this class and those derived from it.
 
vtkSlicerComponentGUI : vtkKWObject
 
    // logic pointers
 
    vtkSlicerApplicationLogic *ApplicationLogic;
 
    vtkMRMLScene *MRMLScene;
 
 
    // API for setting and observing MRML and Logic
 
    void SetMRMLScene ( vtkMRMLScene *mrml );
 
    void SetAndObserveMRMLScene ( vtkMRMLScene *mrml );
 
    void SetApplicationLogic ( vtkSlicerApplicationLogic *logic);
 
    void SetAndObserveApplicationLogic ( vtkSlicerApplicationLogic *logic);
 
 
    // gui methods
 
    BuildGUI ( ) { };
 
 
    // mediator methods, excluded from Tcl wrapping
 
    //BTX
 
    static void MRMLCallback ( vtkObject *caller, unsigned long eid,
 
                              void *clientData, void *callData);
 
    static void LogicCallback ( vtkObject *caller, unsigned long eid,
 
                              void *clientData, void *callData);
 
    static void GUICallback ( vtkObject *caller, unsigned long eid,
 
                              void *clientData, void *callData);
 
    void SetMRML ( vtkObject **nodePtr, vtkObject *node);
 
    void SetAndObserveMRML ( vtkObject **nodePtr, vtkObject *node);
 
    void SetLogic ( vtkObject **logicPtr, vtkObject *logic);
 
    void SetAndObserveLogic ( vtkObject **logicPtr, vtkObject *logic);
 
    //ETX
 
 
    // methods for adding observers onto GUI
 
    virtual void AddGUIObservers ( ) { };
 
    virtual void RemoveGUIObservers ( ) { };
 
 
    // methods to process events
 
    virtual void ProcessLogicEvents ( vtkObject *caller,
 
                        unsigned long eid,void *callData) { };
 
    virtual void ProcessMRMLEvents ( vtkObject *caller,
 
                        unsigned long eid,void *callData) { };
 
    virtual void ProcessGUIEvents ( vtkObject *caller,
 
                        unsigned long eid,void *callData) { };
 
    // entry and exit points
 
    virtual void Enter ( ) { };
 
    virtual void Exit ( ) { };
 
    char *GUIName;
 
 
 
^
 
|
 
 
//---
 
// DERIVE MODULE GUI CLASSES FROM vtkSlicerModuleGUI IF:
 
// your module's GUI will populate Slicer's main
 
// shared UI Panel.
 
vtkSlicerModuleGUI : vtkSlicerComponentGUI
 
  vtkKWUserInterfacePanel *UIPanel;
 
  ...
 
 
//---
 
// DERIVE MODULE GUI CLASSES FROM vtkSlicerComponentGUI IF:
 
// your module creates another toplevel widget or uses
 
// another panel in Slicer's main window in which
 
// to pack its GUI (like vtkSlicerApplicationGUI and
 
// vtkSlicerSliceGUI do.)
 
vtkSlicerApplicationGUI : vtkSlicerComponentGUI
 
//--- ENCAPSULATING SLICER GUI CLASS;
 
// class "partner" of vtkSlicerApplicationLogic;
 
// contains the main Slicer Window;
 
// builds the main Slicer GUI.
 
    vtkKWWindow *MainSlicerWin;
 
    vtkKWMenuButton *ModulesButton;
 
    DisplayMainSlicerWindow ( );
 
    ...
 
 
 
//--- DRAFT SLICER GUI CLASSES
 
// these classes are begun but not currently complete;
 
// they create and manage Slicer's Slice Windows
 
vtkSlicerSlicesGUI : vtkSlicerModuleGUI
 
vtkSlicerSliceGUICollection : vtkCollection
 
vtkSlicerSliceGUI : vtkSlicerComponentGUI
 
vtkSlicerSliceViewer : vtkKWCompositeWidget
 
vtkSlicerSliceController : vtkKWCompositeWidget
 
 
// these other classes are just 'placeholders for now
 
vtkSlicerVolumesGUI : vtkSlicerModulesGUI
 
vtkSlicerModelsGUI : vtkSlicerModulesGUI
 
vtkSlicerDataGUI : vtkSlicerModulesGUI
 
 
// Volumes Module details, as an example.
 
vtkSlicerVolumesGUI : vtkSlicerModuleGUI
 
    vtkSlicerVolumesLogic *VolumesLogic;
 
    vtkMRMLVolumeNode *VolumeNode;
 
    // Widgets
 
      ...
 
    // Get/Set methods on MRML and Logic
 
    // Get/Set methods on Widgets
 
 
    // API for setting and observing Logic and MRML
 
    void SetMRMLNode ( vtkMRMLVolumeNode *node );
 
    void SetAndObserveMRMLNode ( vtkMRMLVolumeNode *node );
 
    void SetModuleLogic ( vtkSlicerVolumeLogic *logic );
 
    void SetAndObserveModuleLogic ( vtkSlicerVolumeLogic *logic );
 
 
    // Redefinition of GUI methods
 
    virtual void BuildGUI ( );
 
 
    // Redefinition of methods for adding observers
 
    virtual void AddGUIObservers ( );
 
    virtual void RemoveGUIObservers ( );
 
 
    // Redefinitions of methods for event processing
 
    virtual void ProcessLogicEvents ( vtkObject *caller,
 
                        unsigned long eid,void *callData) { };
 
    virtual void ProcessMRMLEvents ( vtkObject *caller,
 
                        unsigned long eid,void *callData) { };
 
    virtual void ProcessGUIEvents ( vtkObject *caller,
 
                        unsigned long eid,void *callData) { };
 
 
    // Redefs of Module enter and exit functions
 
    virtual void Enter ( ) { };
 
    virtual void Exit ( ) { };
 
 
    ...
 
 
</nowiki>
 
 
 
=== Current status ===
 
 
 
These classes form a coarse framework for the UI; they're not yet fully developed, they do not have any Slicer3 style applied, still contain some bugs, etc. For the Alpha deadline, we provided a main application window with the general layout described in our current design. For the Beta deadline, we are fleshing out the details of the main window and its GUI features, and working on porting modules.
 
 
 
Some [[Slicer3:Interface_Design_and_Usability:Open_Questions|Current working questions]].
 
 
 
=== Supporting undo ===
 
 
 
A design for supporting undo and redo has been developed. (link to description?)
 
 
 
=== Supporting keyboard shortcuts ===
 
 
 
[[Slicer3:Interface_Design|Return to TOC ]]
 
 
 
= Visual sketches =
 
 
 
Slicer's redesign effort should identify and maintain important UI conventions (helping users to transition more efficiently) and update and improve the design to enhance usability and user experience.
 
 
 
The first task is to redesign the main interface. Some UI conventions on the top-level Slicer2 UI are quite good and should probably be maintained:
 
 
 
* the default 3D + slice window viewer convention;
 
* the axial, sagittal and coronal slice windows and their controls;
 
* the 'slicer blue' background in the 3D window is a strong identifiable feature; if we can keep it, we should! (see notes below);
 
* a pull-down (or hidden until selected) list of slicer modules);
 
* the standard module UI panel, in which an active module's UI is displayed;
 
* the collection of navigator widgets and slice window faders on top level UI (keep, but improve);
 
 
 
It will be useful to add/change:
 
 
 
* a preferences menu in the menu bar;
 
* an edit menu in the menu bar to house "undo/redo"
 
* fwd & back buttons for switching between recently-visited modules
 
* a "home" feature as well, which when configured, will bring the user to the desired slicer module and view configuration;
 
* the UI distinction between slicer core and custom modules.
 
* an indication of keyboard shortcuts on menus
 
* the entire GUI should responsively resize.
 
 
 
In general, the visual design will still be constrained by the formal features of Tk, still at the heart of KWWidgets. Even with Tk tiles, it's unclear how far the appearance of widgets can be stretched. At very least, Tk tiles may be used to maintain a fixed look and feel across platforms, which is desireable.
 
 
 
The sketches below are early working sketches and will be updated as the designs evolve. First steps are to simplifiy the interface, enhance the functional groupings of features for clarity, add new (or expose) features, and to improve the overall appearance.
 
 
 
'''Early layout sketch:'''
 
 
 
[[Image:LayoutSketch.gif|[[Image:LayoutSketch.gif| GUI sketch with KWWidgets / Tk in mind ]]]]
 
 
 
<br /> The sketch shows a draft plan for spatial arrangement of the UI which conforms strongly to Slicer2's comfortable conventions. The default 3D viewer and slicer windows are present and arranged in the familiar fashion, and the color convention that encodes axial, sagittal and coronal slices is maintained (though the hues will change a little bit). On the left, several logical groups of widgets are established and assigned to a GUI panel. The entire left GUI panel should be horizontally collapsable to allow the 3D and slices viewer more screen space. The entire window should resize in a responsive way.
 
 
 
Bottom-most on the GUI panel is the viewer configuration and 3D navigation window. Above that, widgets that control the display of slice windows are grouped. Above that is the panel that contains the GUI for the current active software module. And top-most is the panel that reports which module is currently exposed through the GUI and buttons that let the user navigate to other software modules. The combination of slice and viewer GUI panels should be vertically collapsable so that a module's GUI can have increased screen space.
 
 
 
In the GUI's top panel, only "home, data, volumes, models, and modules" are exposed. Other commonly used modules in the core, (Alignments, Editor, ModelMaker), currently exposed in the top level UI panel, can be listed under the "modules" button in Slicer3. This simplifies the GUI's face and eliminates a potential confusion about which is the "current module" populating the module GUI panel (elaborated below). If it remains important to distinguish core from custom modules, color or font coding can be employed in the modules menu. A user can still navigate to these core modules easily (click, pulldown and release, rather than one-click), and any of these modules can be assigned to the "home" button so that Slicer3 will start up with that module exposed as current. The status report in this panel will always report the current active module, whether core or custom. Simple "forward and back" buttons can allow intuitive navigation, for instance, from the "vtkDTMRI" module to the "alignments" module and back again.
 
 
 
Slicer's logo can be statically displayed in the GUI panel rather than occupying the navigator window when the mouse is elsewhere, and occluding the useful spatial context it provides. The navigator panel, if implemented well, can effectively eliminate the "where'd my model go?" problem that non-expert users sometimes encounter.
 
 
 
In the module GUI panel, options arrayed as tabs in Slicer2 are now displayed in collapsable sub-panels arrayed from top to bottom. This relieves the pressure for space encountered when using horizontally-arrayed notebook tabs, and eliminates Slicer2's workaround "more" tab. (The vertical stack of panels can also coarsely represent a workflow, when that convention needs to be reinforced.)
 
 
 
<br />
 
 
 
'''Slicer-blue versus white 3D viewer background?:'''
 
 
 
Slicer2's 3D viewer has by default a background color that is distinct; images generated with the software are recognized as "Slicer" images in part by this background color, and also by the default window layout (one 3D on 3 slice windows) they depict. The background blue may also help disambiguate white features in the data from the void of the background. Keeping this background color convention is something we'd like to do.
 
 
 
Having a medium-high-valued luminance, the color does pose some limitations on the display of small textual annotations with good readable contrast in the 3D viewer. In Slicer2, annotations in this space are rendered readable in at least two ways: by making them '''large and bold''', or placing them on small polygons that lighten the area behind the text. Both of these are compromises; annotations take up more space in the view than is necessary, and they are assigned a look of importance that's not conceptually justified. Ideally, we'd like to display clearly readable text in a range of sizes and colors in the 3D viewer, both to support visualizations of complicated data in a subordinate way, and as actors populating an information space in their own right.
 
 
 
A quick exploration of the challenge is illustrated below. Avoiding equiluminant colors is important for good readability no matter what the background color. On the blue background, it appears the best color contrast is given from colors in the draft Slicer3 palette ranging from "black" to "brick" whose value is low and/or color contrast is high. Highly saturated red and magenta contrast well too, though their garrishness gives them an almost "alert" visual priority. For small text, black or dark grey is probably best advised. However, to render a multi-colored textual information space, changing the background color in the 3D viewer to white is probably the best way to avoid some hard-to-read labels.
 
 
 
[[Image:ColorTest.jpg|[[Image:ColorTest.jpg| medium luminance background poses contrast challenge ]]]]
 
 
 
<br />
 
 
 
= Design drafts =
 
 
 
== Slicer main window ==
 
 
 
Slicer3 main menu working draft and one variation with a white 3D viewer are shown below. This draft is working out logical groupings of GUI functionality and converging toward a draft design. This design adheres to a traditional Tk (and BLT) look, which is more dated than we'd prefer. In a future draft, we'll modify the design of core widgets as the upcoming new release of Tk and/or Tk Tile will permit us to put a more modern (and hopefully platform independent) face on the GUI.
 
 
 
In this sketch, the GUI background is rendered as a clean and pristine white, is kept as uncluttered as possible, and incorporates color sparingly, for grouping related components, and to encode certain concepts (such as "selected", "active", "unsaved", ''etc.''). Use of the hairline helps to make the layout appear sharp and precise. Window title bars are shown using Slicer3 palette's warm greys, with a soft gradient to give them a little distinction from other elements (disambiguating the title bar from the rest of the GUI can help a user to easily target it with the mouse to move it around a busy screen.)
 
 
 
Ideas from the sketch above were incorporated and have been modified and refined. In particular, GUI has been partitioned into 5 logical chunks:
 
 
 
* file menu
 
* application navigation panel
 
* current module interface
 
* slice window configuration panel
 
* view configuration panel
 
* progress bar & message panel
 
 
 
The entire side gui panel can be collapsed or reset using the "expand/collapse" icon in its upper right corner. A keyboard shortcut will also toggle the GUIs visibility. The file menu adds an "edit" option (to contain undo/redo functionality) and a "preferences" option (to save settings like a "home" module and preferred view configuration), in addition to those that already exist in Slicer. Forward and Back icons have been added next to the "module" pull-down menu, so that a user can easily navigate between modules recently visited.
 
 
 
Prescribing dual functionality to the slice window slider, depending on a mode switch, to dial slice opacity or crossfade seems natural and compact. Bringing the ability to turn on and off annotations in the viewer from the main GUI panel is also handy. A more elaborate navigation window is shown (based on Photoshop's) and a re-do of the "rotate around" or "view from" axis icons is presented, without the rendered head in Slicer2's version. These have been combined into one, for a more compact solution. For clarity, when the "rotate" mode is selected, mousing over "A" or "P" in the icon will highlight both; same for "R" and "L", and for "S" and "I". When "view" mode is selected, only the "A", "P", "R", "L", "S" or "I" under the mouse should be highlighted. Finally, five configurations are selectable for the main viewer: default 3D over Axi-Sag-Cor; 3D only; four-up; saved view notebook; and lightbox. Selecting any one of these should switch the viewer's configuration.
 
 
 
In general, the sketches remove all literal images of human anatomy from the interface; while Slicer's software modules are designed primarily for medical data analysis and visualization, other research domains should certainly feel comfortable developing and using custom modules suited to their applications, or use existing modules with different types of data.
 
 
 
The sketch incorporates the primary action patterns that have been identified in Slicer's UI: narrative (serial workflow coarsly represented in the module GUI panel), high-density information display with direct manipulation, a status display (current module, progress bar, system messages), a navigator window for maintaining spatial context, and a control panel for configuring the view, configuring and executing data processing.
 
 
 
Notes: the color "stoneTint" in the Slicer3 palette, used to delimit entry widgets, buttons and listbox, is still too pink and we want to depart from Slicer2's pinkness. Need to take this color more toward a cool light brown or a warm light grey (same thing?!)...
 
 
 
<br />[[Image:SlicerLookFeelDraftSmall.jpg|[[Image:SlicerLookFeelDraftSmall.jpg| working draft... ]]]] [[Image:SlicerLookFeelWhiteViewer.jpg|[[Image:SlicerLookFeelWhiteViewer.jpg| working draft variation... ]]]]
 
 
 
'''Early (working) design of GUI panel full resolution:'''
 
 
 
[[Image:SlicerLookFeelSideDraft.jpg|[[Image:SlicerLookFeelSideDraft.jpg| still working on this... ]]]]
 
 
 
<br />
 
  
== Toolbar with icons ==
+
= User Interface Guidelines for Developers =
  
Ron has requestsed a persistent toolbar for one-click navigation to commonly-used slicer utilities and modules. We are implementing this now in the Slicer Main Window. Below is a design draft for icons to be included. The slice plane visibility icons are not meant for the toolbar -- these texture a pushbutton in the Slice Window Controller and switch (visible/invisible) to display the state of slice plane visibility in the Main Viewer.
+
== General Principles ==
  
<br />[[Image:SlicerToolbarIcons.png|[[Image:SlicerToolbarIcons.png| draft design for comment ]]]]
+
=== Look and Feel ===
  
<br />
+
=== Module style ===
  
[[Slicer3:Interface_Design|Return to TOC ]]
+
=== Pop-up windows ===
  
= Documentation and design guidelines =
+
=== Confirm on Delete ===
  
OSS projects that have significant usability efforts include (notably) GNOME, KDE, Mozilla, and OpenOffice.org; all have usability teams and have published UI specs, guidelines or usability studies. By following these guidelines, open source development projects can maintain consistent interface conventions, making the software more visually coherent and often easier to learn.
+
== Application Font ==
  
The Slicer3 interface guidelines are being developed here; once established, where possible, they should be followed by developers, in Slicer's web presence and in training and documentation materials.
+
The Slicer3 theme sets the application font to be Helvetica 8 normal. The Slicer3 logo font is Verdana.
  
The topic is broken into three themes:
+
== Icons ==
  
* Slicer3 brand
+
== Providing help ==
* Design practice for developers
 
* Design guidelines for developers
 
  
<br />
+
== Popup messages (dialog, warning, error, confirm, etc. ==
  
== Slicer3 brand ==
+
== Language ==
  
* New slicer logo
+
== Credit and Logos ==
* Slicer font(s) and text conventions
 
* Slicer color palette:
 
  
Early sketches for a new slicer logo are included below; some quick experiments. We'll keep a wiki sketchbook record of the evolving design... comments about this initial set of experiments: "3D" looks too much like "ED" on the filled text especially; the vertical lines look too much like barcodes; the presence of some organic shape might be nice; and the perspective slices look a little jaggy and scary, especially when combined with "slicer".
+
== Keyboard interaction ==
  
Other comments that came out of a discussion of these sketches at the Slicer3 project meeting on 4/3/06:
+
== Controls and Layout ==
  
* It's important to invoke some sense of our existing Slicer logo in the new Slicer logo.
+
== Progress Feedback ==
* Ron favors the top right version including its color scheme out from among the sketches below. Issues: the unclosed square fails to strongly convey the sense of three-dimensionality, and the font in this (and other similar versions) sketch feel a little retro; this deviates from the core values our brand should convey.
 
* Need to make sure the logo can keep its integrity across many different physical scales, the smallest version might be included in a web browser's navigation tool bar.
 
  
<br />[[Image:LogoSketches.jpg|[[Image:LogoSketches.jpg| logo sketches ]]]].
+
== Colors: application palette ==
  
The draft slicer color palette is shown below (this palette will still evolve as the UI design evolves). Developers of code, web content and training materials are encouraged to make color choices for GUI components according to this palette, bearing in mind that some of the colors are linked with special meaning, such as error (red), warning (bright yellow), and system (mediumBlue) messages, and unsaved data in drop-down menus and selection boxes (warmMediumGrey).
+
The draft slicer color palette is shown below (this palette will still evolve as the UI design evolves -- in particular to accommodate colors used in the final Slicer3 logo). Developers of code, web content and training materials are encouraged to make color choices for GUI components according to this palette, bearing in mind that some of the colors are linked with special meaning, such as error (red), warning (bright yellow), and system (mediumBlue) messages, and unsaved data in drop-down menus and selection boxes (warmMediumGrey).
  
 
[[Image:Slicer3Palette.jpg|[[Image:Slicer3Palette.jpg| Slicer GUI color palette (not applicable to visualization)]]]]
 
[[Image:Slicer3Palette.jpg|[[Image:Slicer3Palette.jpg| Slicer GUI color palette (not applicable to visualization)]]]]
Line 719: Line 321:
 
[[Image:PopupDialog.jpg|[[Image:PopupDialog.jpg| draft dialog box (error, warning, system messages)]]]]
 
[[Image:PopupDialog.jpg|[[Image:PopupDialog.jpg| draft dialog box (error, warning, system messages)]]]]
  
[[Slicer3:Interface_Design|Return to TOC ]]
+
== How to build a Slicer3 Module GUI ==
 
 
== Design practice for developers ==
 
 
 
<br />
 
 
 
== Design guidelines for developers ==
 
 
 
= Usability =
 
 
 
== Core domain uses & needs assessment ==
 
 
 
The most basic usability requirement for any software package is a thorough understanding of who the target audience is. Our Slicer3 development funding designates the following communities to be among our core user groups, though the package is used in many other scenarios as well. In design and development, we're targetting these core communities, but we welcome and encourage input from any others.
 
 
 
Core user communities:
 
 
 
* (NAC) Longitudinal and multi-channel dataset analysis
 
* (BIRN/NA-MIC) Individual and group analysis
 
* (IGT/AMIGO) Real-time control and tracking in the operating theater
 
* (IGT) Neurosurgical planning and guidance
 
  
== Notes on OSS and user-centered design ==
+
First, note that the GUI base classes may be refactored as Slicer3 develops; it's recommended that you check documentation periodically for new base class methods which may be useful. The figure below shows a current overview of the three classes a new module (called MyModule for example) will need to define (vtkSlicerMyModuleGUI, vtkSlicerMyModuleLogic and vtkMRMLMyModuleNode) and some of the methods those classes should include to utilize the Slicer3 infrastructure. These classes should reside in the slicer3/Modules/MyModule/ directory.
  
As an open source software effort ''and'' artifact, Slicer has a unique compound characterization; it's an extensible platform for research and development with a fairly consistent coding style; an interactive end-user application with high-performance C++ image analysis and rendering and a fairly consistent user interface, and a supported mechanism for translating emerging tools rapidly from research laboratories to both user and developer communities.
+
[[Image:Slicer3MyModule.png|[[Image:Slicer3MyModule.png| Base classes for GUI, Logic and MRML ]]]]
  
Culturally, as in many OSS efforts, most of Slicer's underlying architecture and user interface have been developed by a large community over time, lead and framed by strong technology vision, but without a coupled interface/interaction design and usability effort.
+
'''Deriving your GUI class:''' To create a Module GUI that expresses its interface in Slicer's shared UIpanel, derive your class (vtkSlicerMyModuleGUI) from vtkSlicerModuleGUI. For a Module GUI that expresses its interface in a different panel of the Main Slicer Window, or in a toplevel widget, derive vtkSlicerMyModuleGUI from vtkSlicerComponentGUI instead. Your GUI class will inherit application logic and MRML pointers, an API for setting and observing them, and a framework for defining MRML, Logic and GUI callbacks from its parent class. Specific mediator methods, other logic and MRML node pointers can be added to the module's class definition. Importantly, keep logic and MRML classes independent of the GUI to facilitate testing and command-line execution possible *without* instantiating the Slicer3 GUI.
  
Recently, OSS projects such as GNOME, KDE, Mozilla and OpenOffice.org have had notable success in incorporating usability teams into their efforts. While the typical role of interface designers and usability experts in the development of commercial products is well known and very deeply coupled, the manner in which a user-centered design effort can interact with and productively shape OSS development remains a challenging topic.
+
'''Example:''' An early example to work from is the GradientAnisotropicDiffusionFilter Module; define all the widgets you need within the class and create Get Macros for each of them. Define the methods you need from vtkSlicerModuleGUI and its parent class vtkSlicerComponentGUI, including BuildGUI(); in this method, you'll first add a page to the class's UIPanel (for now, only create one page).
  
For example, in industry, usability experts are involved in development before coding even begins, and their designs strongly shape the form, behavior and etiquette of a software product throughout its development cycle. Many open source developers enjoy coding for themselves, as part of a distributed working meritocracy, developing according to their own -- and often excellent -- intuitions. While the success of projects like GNOME inspire interest in collaborating to promote both technology excellence and usability, no standard prescription extists yet for how to implement that collaboration.
+
'''Two styles:''' Depending on whether you want a notebook-style GUI for your module (similar to the style used in Slicer2) or a set of stacked collapsible frames to contain different logical sections of your interface like "help" and "display", your BuildGUI() method can be written in one of two ways. The '''notebook style''' may be appropriate for modules with long logical sections within their GUI, to minimize the amount of scrolling required of a user. The '''collapsing style''' may be appropriate for modules that have numerous logical sections, since the amount of horizontal space across which a notebook would array them is limited. The way these two styles are expressed in Slicer3's GUI panel is shown below.
  
We can look at the GNOME project as a case study: In March 2001, Sun Microsystems performed a three-day GNOME usability study (Smith S, Engen D, Mankoski A, ''et al.'', "GNOME Usability Study Report", Sun Microsystems, July 2001) and results were subsequently presented at a GNOME users and developer's conference (GUADEC). The study recruited a dozen technical, business and creative professionals with computer experience, but none with GNOME. Participants were tasked with logging in, commenting on the desktop, customizing the desktop and managing files. Their report categorized and itemized important feedback from participants, and offered design recommendations. (note: link to study). This presentation marked the first time many GNOME developers became aware of the user community's experiences with the software.
+
[[Image:S3ModuleStyles.png|[[Image:S3ModuleStyles.png| Image:S3ModuleStyles.png]]]]
  
Shortly afterward, a usability team was formed within the project, tasked first with developing a set of guidelines (now the GNOME Human Interface Guildelines, HIG 2.0) against which GNOME applications are checked for conformance prior to release. The team also introduced a usability keyword for bug reporting so that usability-related bugs could be properly tracked and assigned. Other OSS efforts have formed usability teams too (''i.e.'' KDE Usability Project and Mozilla UI Sector) and have published their own usability studies and sets of usability guidelines (''i.e.'' KDE Human Interface Guidelines). (note: link to guidelines).
+
'''''Collapsing style:''''' The GradientAnisotropicDiffusionFilter Module example implements the collapsible style, first adding a single new Page in its UIPanel:
  
Strategies for building open source software tools that users love to use can still be greatly improved. Some of the following issues are noted as current challeges for advocates of usability in OSS efforts (Benson C. "Meeting the challenge of open source software usability", ''Interfaces'' 60, Autumn 2004):
+
  this->UIPanel->AddPage ( "MyModule", "MyModule", NULL );
  
* Encouraging a thorough understanding of the core user community;
+
then creating a vtkSlicerModuleCollapsibleFrame widget for each logical section in the GUI, parenting each to the UIPanel's single PageWidget, then creating, configuring and packing them from top to bottom in the UIPanel's PageWidget. Each logical section's widgets can be organized inside each of the vtkSlicerModuleCollapsibleFrames.
* Having a usability team consult more deeply in the development process;
 
* Adopting distinct ways to regard and address usability and functionality bugs;
 
* Developing OSS tools that automate generation of guideline-compliant interfaces for developers;
 
* Creating convenient oportunities and mechanisms for users to comment on usability issues;
 
* Finding ways to share and consolidate experience among usability teams across OSS projects;
 
  
To address the last issue, some useful resources exist, notably openusability.org, which has a useful bibliography linking to usability discussions, relevant articles, news, guildelines and published studies. Openusability.org is a professional meeting ground for open source developers and usability experts, and clarifies very simply the benefit of their collaboration: "There are many Usability Experts who want to contribute to software projects. And there are many Developers who want to make their software more usable, and as a consequence, more successful."
+
  vtkSlicerModuleCollapsibleFrame *helpFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 +
  vtkSlicerModuleCollapsibleFrame *firstFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 +
  vtkSlicerModuleCollapsibleFrame *secondFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 +
  vtkSlicerModuleCollapsibleFrame *thirdFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 +
  vtkSlicerModuleCollapsibleFrame *forthFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 +
  ...
 +
  helpFrame->SetParent ( this->UIPanel->GetPageWidget ( "MyModule" ) );
 +
  firstFrame->SetParent ( this->UIPanel->GetPageWidget ( "MyModule" ) );
 +
  secondFrame->SetParent ( this->UIPanel->GetPageWidget ( "MyModule" ) );
 +
  ...
 +
  this->widget1->SetParent ( helpFrame->GetFrame () );
 +
  this->widget2->SetParent ( firstFrame->GetFrame () );
 +
  this->widget3->SetParent ( secondFrame->GetFrame () );
  
== Slicer3 design and development climate ==
+
'''''Notebook style:''''' To create a notebook style GUI (as there is no example yet, a little code will be included here), a new Page must be added to the UIPanel for every tab in the notebook:
  
OSS projects express their own distinct cultures, and each likely presents an unique and interesting climate in which to launch a user-centered design component. For the Slicer3 effort, we're developing a new user interface within a very active OS development environment which has adopted the "Extreme Programming" methodology. Developers communicate and work collaboratively via local meetings, weekly t-cons, a dedicated wiki, intermittent programming meetings, using shared CVS and Subversion code repositories. At the start of this project, no usability studies have looked at earlier versions of Slicer, or any of its many individual components. A coarse style guide exists in the form of a limited preferred-use widget set, and conventions for color-coding, fonts, GUI layout, providing help, tooltips, and documentation. Members of our small usability team are also members of the Slicer developer community, and have worked with and developed software explicitly for members of Slicer's user community. As such, we're starting this effort with a good understanding of both of these communties, and a strong sense of the core values of the Slicer effort and the software artifact.
+
  this->UIPanel->AddPage ( "Help", "Information about using this module", NULL );
 +
  this->UIPanel->AddPage ( "First", "Functionality for some logical piece of module", NULL );
 +
  this->UIPanel->AddPage ( "Second", "Functionality for another logical piece of module", NULL );
  
== Introduction of usability issues at the NA-MIC all-hands meeting ==
+
Widgets to be packed within each notebook page are parented to the PageWidget:
  
A discussion about usability engineering was launched (at the NA-MIC AHM in Utah in January) to guage general interest, and gather ideas about how to integrate usability design into the Slicer3 development effort.
+
  this->widget1->SetParent ( this->UIPanel->GetPageWidget ( "Help" ) );
 +
  this->widget2->SetParent ( this->UIPanel->GetPageWidget ( "First" ) );
 +
  this->widget3->SetParent ( this->UIPanel->GetPageWidget ( "Second" ) );
  
The disucssion focused on the successes of the GNOME project, and their HIG 2.0 in particular. We discussed the value of developing a set of similar guidelines for Slicer3 as a first step toward producing a technically excellent and highly usable software package, determine what part of the GNOME HIG we might use or modify, and what extra considerations may be important for Slicer3, as medical image analysis and visualization software. Establishing guidelines has been a common first-step among many new OSS usability efforts.
+
or to a widget already parented to it, created, configured, and packed in the same manner as they are in the GradientAnisotropicDiffusionFilter Module.
  
In addition, we had a separate technology specific discussion aimed at selecting an appropriate GUI toolkit for use in Slicer3 UI development. At the meeting, we learned more about KWWidgets from Kitware, and experimented with the toolkit.
+
'''Methods to define:''' Define the methods you require from vtkSlicerComponentGUI base class, like: AddGUIObservers(), RemoveGUIObservers(), ProcessLogicEvents(), ProcessGUIEevents(), ProcessMRMLEvents(), Enter() and Exit(); and whatever else your module needs. (Eventually, available modules will be automatically detected, but this is not yet implemented; then, the Enter() method will probably be made to call the BuildGUI() method. For now, instantiate your class in Slicer3.cxx and call its BuildGUI() and other methods, following the pattern for other modules established there.)
  
= Evaluating technology resources =
+
'''Adding observers:''' In AddGUIObservers, add an observer on each widget whose events you want to process. When an event is observed, the ProcessGUIEvents() method is called via the GUICallbackCommand; define this class to propagate information from the GUI to logic and MRML. Though it is tempting, try not to use ProcessGUIEvents() to update the GUI state directly -- just modify the Logic state, and allow observers on the logic and subsequent processing in ProcessLogicEvents() and ProcessMRMLEvents() to bring that state change BACK into the GUI.
  
== Practical factors to consider: ==
+
'''Removing observers:''' In RemoveGUIObservers, make sure you remove every observer you've added to widgets in the GUI before calling Delete() on your widget. Make sure you call SetAndObserveMRML() and SetAndObserveLogic( ) with NULL pointers in your GUI class destructor to remove all observers on MRML and Logic that you have created.
  
* List of widgets and composite widgets we believe are required to both simplify the porting of existing Slicer modules, and to develop new commonly-used tools for viewing and interaction:
+
'''Defining your own widgets:''' The framework for doing this is still evolving. Currently there are two types of new widgets, those defined as extensions to vtkKW (like vtkKWWindowLevelThresholdEditor.h/cxx) and those defined as Slicer-specific widgets, (like vtkSlicerSliceControlWidget.h/cxx, derived from the vtkSlicerWidget.h/cxx base class). The Slicer widgets have methods for putting observers on their widget components, Logic and MRML, and processing events as well. Thus GUI classes that instance them do not have to manage events for them if the widgets' methods are used instead.
  
'''basic widgets: ''' Top-level widgets, frames, tabs (or other structural dividers), dialogs, messagebox, button, radio button, slider, scrollbar, thumbwheel, colorwheel, file browser, listbox, entry, canvas, label, bitmap widget, rich text or html widget, checkbox, menu (pulldown, cascaded) and menu button, graph/chart, histogram, table, tree, (continue)….
+
'''Undo:''' Make sure you process those events that mark junctures at which MRML state should be saved for Undo/Redo (using MRML's SaveStateForUndo() method. For an example of they way this method is called, see slicer3/Base/GUI/vtkSlicerSliceControllerWidget.cxx.
  
'''composite widgets:''' File entry + browse button with consistent filtering convention, File search, Add and remove box, Slice viewer (for single and multi-volume / time-series), Multi-slice viewer (for single and multi-volume / time-series), 3D Viewer, Single pane info viz viewer (for data not to be seen in spatial context of 3D viewer.), lightbox viewer (for single and multi-volume / time-series), layers editor for compositing/viewing (behavior for multi-modal data?), Transfer function editor, Material editor (surface properties, etc.), Volume selector, Model selector, MRML node properties dialog box, Data model viewer (hierarchy editor), Task viewer, Console or log widget, Container and contents, (continue)…
+
'''GUI Style:''' Try not to add style elements (like foreground and background color, font, relief, etc.) to the interface you create; let the options database (as set up by the vtkSlicerTheme class) specify the style for you so that all modules appear consistent within the Slicer3 application.
  
* Developer-friendly programmer interface?
+
'''Other files you will have to touch:''' For now, to add your module to Slicer3, create a new instance of vtkSlicerMyModuleLogic and vtkSlicerMyModuleGUI in Applications/GUI/Slicer3.cxx, and follow the pattern used by the GradientAnisotropicDiffusionFilter module for now, until the framework is developed for Slicer3 to autodetect your module and do the right things. You should also create your own CMakeLists.txt file in your module directory and (follow the example in other Module directories), add your module to Modules/CMakeLists.txt, and to Applications/GUI/CMakeLists.txt.
* Good resources for programmers?
 
* Good design space for UI designers?
 
* Proposed GUI layer model & application layer support requirements?
 
* Compatible with proposed data model?
 
* Scriptable for automated testing?
 
* ...
 
  
== Resources ==
+
<br />[[Slicer3:Interface_Design|Return to Slicer3 Interface Design and Usability ]]
 
 
* Existing GUI toolkits
 
* Wrapping
 
* Application framework libraries
 
* Layout design tools?
 
* Programming languages
 
* Platform support
 
* Debugging tools?
 
* Compatible license
 
* Existing style guides
 
 
 
=== Crossplatform GUI toolkit comparisons ===
 
 
 
Here's a start on a matrix comparing some crossplatform toolkit options (please help fill in info and correct any bugs):
 
 
 
{| border="1"
 
|- bgcolor="#abcdef"
 
!
 
! KWWidgets
 
! Tcl/Tk
 
! GTK+
 
! Qt
 
! FLTK
 
! wxWidgets
 
! FOX toolkit
 
! Tkinter
 
|-
 
| Linux
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
| (python)
 
|-
 
| Unix/X11
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
|
 
|-
 
| Unix/Motif
 
|
 
|
 
|
 
| y
 
| y
 
| y
 
| y
 
|
 
|-
 
| Win95/98
 
| y
 
| y
 
| y
 
| y
 
|
 
| y
 
| y
 
|
 
|-
 
| NT/2000
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
|
 
|-
 
| Win3.1
 
|
 
| y
 
|
 
|
 
|
 
| y
 
|
 
|
 
|-
 
| OS/2
 
|
 
|
 
|
 
|
 
|
 
| (in prog)
 
|
 
|
 
|-
 
| MacOS
 
| y
 
| y
 
|
 
|
 
|
 
| y
 
|
 
|
 
|-
 
| OSX (Carbon)
 
| y
 
| y
 
| alpha
 
| y
 
| y
 
| y
 
| (with Xerver)
 
|
 
|-
 
| License
 
| BSD-style
 
| BSD
 
| LGPL
 
| GPL
 
| LGPL<br /> but allows static linking
 
| LGPL<br />(with an exception stating that derived works in binary form may be distributed on the user's own terms)
 
| LGPL
 
| Python
 
|-
 
| Testable?
 
| y
 
|
 
|
 
|
 
|
 
|
 
|
 
|
 
|-
 
| Language & bindings
 
| C++; Tcl/Tk; python
 
| C; Tcl, python, java
 
| C; perl, python, Java, Tcl, etc.
 
| C++; python, java
 
| C++; Tcl, Python
 
| C++; Python, java, perl...
 
| C++; Python
 
| Python bindings for Tcl
 
|-
 
| Full widget set?
 
| y
 
| n
 
| y
 
| y
 
| y
 
| y
 
| y
 
| n
 
|-
 
| Customize? widgets/style
 
| n/native
 
| n/native
 
| y (hard)/Motif-like
 
| y/native
 
| y/?
 
| y/native
 
| y/win95
 
| n/native
 
|-
 
| Easy debugging?
 
| C++
 
|
 
|
 
| C++
 
|
 
| C++
 
|
 
|
 
|-
 
| freshmeat vily/pop%
 
|
 
| 0.19/9.92
 
| 0.59/24.45
 
| ,28/20.97
 
| 0.05/6.38
 
| 0.1/6.17
 
| 100/10.43
 
| 0.00/0.36
 
|-
 
| good docs?
 
| brief
 
| y
 
| y
 
| y
 
| y
 
| y
 
| y
 
| brief
 
|-
 
| comments
 
|
 
|
 
|
 
|
 
|
 
|
 
|
 
|
 
|}
 
  
=== Resource links ===
+
= Current working questions =
  
(include links below; having trouble saving the page with external links...)
+
Some [[Slicer3:Interface_Design_and_Usability:Open_Questions|Current working questions on implementation]].
  
* GUI toolkit information
+
= Feature Requests, Resource Requests and Emerging Conventions =
  
* UI Style guides and usability info:
+
We are collecting '''[[Slicer3:FeatureRequests|feature, conventions and resource requests]]''' from users and developers. Appropriate entries from [http://www.na-mic.org/Bug Slicer2's bug tracker] will be periodically added to this repository also.
  
 
<br />
 
<br />

Revision as of 13:26, 18 December 2006

Home < Slicer3:Interface Design and Usability

<< Back to Slicer3 main page

Also see AHM 2006 >>

Working notes: Slicer3 GUI and its application interface:


Project goals

Design and engineer Slicer3 UI. Employ a user-centered approach and establish usability guidelines.

Project reporting

The scope of this effort is sorted into four categories: Engineering, UI design, Usability and Slicer3 branding. The subtasks of each category are itemized below and specific information about each category is located on the linked pages.

UI Architecture & Engineering

Tasks: (more detailed UI Architecture & Engineering information can be found here).

  • design thin GUI layer, separate from the control logic and data model;
  • design a model for representing the UI and managing local events;
  • extend the model for handling remote events;
  • design means of mapping KWWidgets onto that model;
  • set priorities with Kitware involving extensions & modifications to KWWidgets;
  • determine the api to application logic, used by GUI and by scripts;
  • design set of base classes that give module developers an easy pattern to follow;
  • develop guidelines for slicer base developers and module developers;
  • design mechanism for centrally specifying look & feel (and permitting overrides);

UI Design & Prototypes

Tasks: (more detailed UI Design & Prototype information can be found here ).

  • design overall look to Slicer3 application in keeping with core values;
  • design look & feel applied to developer modules;
  • design KWWidgets class to specify custom widgets for Slicer main app & modules;
  • implement Slicer3 Application GUI
  • design conventions for specifying global and module-specific keyboard accelerators;
  • specify and document global keyboard accelerators;
  • iterate on prototype(s) and present them for comments and suggestions;

Usability

Tasks: (more detailed Usability information can be found here ).

  • determine which Slicer3 tools will require user studies and user testing;
  • develop mechanisms for user feedback on usability issues.
  • interview core user community members to investigate general and domain-specific usability issues, user requirements, technical requirements.
  • consolidate and report what is learned for reference and use in design process
  • test designs with members of the user community, analyze testing results & iterate
  • develop and publish design guidelines to support usability and software consistency.

Slicer3 Brand

Tasks: (Slicer3 brand sketches can be foundhere ).

  • fully express Slicer3 brand: design logo, splash screen, style sheets for web presence;

User Interface Guidelines for Developers

General Principles

Look and Feel

Module style

Pop-up windows

Confirm on Delete

Application Font

The Slicer3 theme sets the application font to be Helvetica 8 normal. The Slicer3 logo font is Verdana.

Icons

Providing help

Popup messages (dialog, warning, error, confirm, etc.

Language

Credit and Logos

Keyboard interaction

Controls and Layout

Progress Feedback

Colors: application palette

The draft slicer color palette is shown below (this palette will still evolve as the UI design evolves -- in particular to accommodate colors used in the final Slicer3 logo). Developers of code, web content and training materials are encouraged to make color choices for GUI components according to this palette, bearing in mind that some of the colors are linked with special meaning, such as error (red), warning (bright yellow), and system (mediumBlue) messages, and unsaved data in drop-down menus and selection boxes (warmMediumGrey).


color R G B hex use in slicer
black 0 0 0 #000000
white 255 255 255 #ffffff GUI background
darkWarmGrey 96 94 83 #605e53
mediumWarmGrey 139 136 120 #8b8878 unsaved data ?
lightWarmGrey 205 200 177 #cdc8b1
warmGreyTint 238 232 220 #eee8dc
darkOrange 196 74 26 #c44a1a
brightOrange 224 111 19 #e06f13
brightYellow 231 209 62 #e7d13e warning message code
yellowTint 238 214 128 #eed680 sag slice
darkCocoa 130 102 71 #826647
lightCocoa 179 145 105 #b39169
stone 224 195 158 #e0c39e
stoneTint 239 224 205 #efe0cd
red 195 46 15 #c32e10 error message code
brick 186 70 43 #ba462b
lightBrick 193 115 80 #c17350 axi slice
redTint 224 182 175 #e0b6af
darkGreen 68 86 50 #445632
brightGreen 104 143 66 #688f42
dustyGreen 138 165 111 #8aa56f cor slice
greenTint 204 244 166 #ccf4a6
darkBlue 73 64 102 #494066
mediumBlue 98 91 129 #625b81 system message code
lightBlue 136 127 163 #887fa3 unsaved data?
slicerBlue 179 179 230 #b3b3e6


This prototype dialog box is an example of Slicer3's limited use of color coding:

How to build a Slicer3 Module GUI

First, note that the GUI base classes may be refactored as Slicer3 develops; it's recommended that you check documentation periodically for new base class methods which may be useful. The figure below shows a current overview of the three classes a new module (called MyModule for example) will need to define (vtkSlicerMyModuleGUI, vtkSlicerMyModuleLogic and vtkMRMLMyModuleNode) and some of the methods those classes should include to utilize the Slicer3 infrastructure. These classes should reside in the slicer3/Modules/MyModule/ directory.

Deriving your GUI class: To create a Module GUI that expresses its interface in Slicer's shared UIpanel, derive your class (vtkSlicerMyModuleGUI) from vtkSlicerModuleGUI. For a Module GUI that expresses its interface in a different panel of the Main Slicer Window, or in a toplevel widget, derive vtkSlicerMyModuleGUI from vtkSlicerComponentGUI instead. Your GUI class will inherit application logic and MRML pointers, an API for setting and observing them, and a framework for defining MRML, Logic and GUI callbacks from its parent class. Specific mediator methods, other logic and MRML node pointers can be added to the module's class definition. Importantly, keep logic and MRML classes independent of the GUI to facilitate testing and command-line execution possible *without* instantiating the Slicer3 GUI.

Example: An early example to work from is the GradientAnisotropicDiffusionFilter Module; define all the widgets you need within the class and create Get Macros for each of them. Define the methods you need from vtkSlicerModuleGUI and its parent class vtkSlicerComponentGUI, including BuildGUI(); in this method, you'll first add a page to the class's UIPanel (for now, only create one page).

Two styles: Depending on whether you want a notebook-style GUI for your module (similar to the style used in Slicer2) or a set of stacked collapsible frames to contain different logical sections of your interface like "help" and "display", your BuildGUI() method can be written in one of two ways. The notebook style may be appropriate for modules with long logical sections within their GUI, to minimize the amount of scrolling required of a user. The collapsing style may be appropriate for modules that have numerous logical sections, since the amount of horizontal space across which a notebook would array them is limited. The way these two styles are expressed in Slicer3's GUI panel is shown below.

Collapsing style: The GradientAnisotropicDiffusionFilter Module example implements the collapsible style, first adding a single new Page in its UIPanel:

 this->UIPanel->AddPage ( "MyModule", "MyModule", NULL );

then creating a vtkSlicerModuleCollapsibleFrame widget for each logical section in the GUI, parenting each to the UIPanel's single PageWidget, then creating, configuring and packing them from top to bottom in the UIPanel's PageWidget. Each logical section's widgets can be organized inside each of the vtkSlicerModuleCollapsibleFrames.

 vtkSlicerModuleCollapsibleFrame *helpFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 vtkSlicerModuleCollapsibleFrame *firstFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 vtkSlicerModuleCollapsibleFrame *secondFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 vtkSlicerModuleCollapsibleFrame *thirdFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 vtkSlicerModuleCollapsibleFrame *forthFrame = vtkSlicerModuleCollapsibleFrame::New ( );
 ...
 helpFrame->SetParent ( this->UIPanel->GetPageWidget ( "MyModule" ) );
 firstFrame->SetParent ( this->UIPanel->GetPageWidget ( "MyModule" ) );
 secondFrame->SetParent ( this->UIPanel->GetPageWidget ( "MyModule" ) );
 ...
 this->widget1->SetParent ( helpFrame->GetFrame () );
 this->widget2->SetParent ( firstFrame->GetFrame () );
 this->widget3->SetParent ( secondFrame->GetFrame () );

Notebook style: To create a notebook style GUI (as there is no example yet, a little code will be included here), a new Page must be added to the UIPanel for every tab in the notebook:

 this->UIPanel->AddPage ( "Help", "Information about using this module", NULL );
 this->UIPanel->AddPage ( "First", "Functionality for some logical piece of module", NULL );
 this->UIPanel->AddPage ( "Second", "Functionality for another logical piece of module", NULL );

Widgets to be packed within each notebook page are parented to the PageWidget:

 this->widget1->SetParent ( this->UIPanel->GetPageWidget ( "Help" ) );
 this->widget2->SetParent ( this->UIPanel->GetPageWidget ( "First" ) );
 this->widget3->SetParent ( this->UIPanel->GetPageWidget ( "Second" ) );

or to a widget already parented to it, created, configured, and packed in the same manner as they are in the GradientAnisotropicDiffusionFilter Module.

Methods to define: Define the methods you require from vtkSlicerComponentGUI base class, like: AddGUIObservers(), RemoveGUIObservers(), ProcessLogicEvents(), ProcessGUIEevents(), ProcessMRMLEvents(), Enter() and Exit(); and whatever else your module needs. (Eventually, available modules will be automatically detected, but this is not yet implemented; then, the Enter() method will probably be made to call the BuildGUI() method. For now, instantiate your class in Slicer3.cxx and call its BuildGUI() and other methods, following the pattern for other modules established there.)

Adding observers: In AddGUIObservers, add an observer on each widget whose events you want to process. When an event is observed, the ProcessGUIEvents() method is called via the GUICallbackCommand; define this class to propagate information from the GUI to logic and MRML. Though it is tempting, try not to use ProcessGUIEvents() to update the GUI state directly -- just modify the Logic state, and allow observers on the logic and subsequent processing in ProcessLogicEvents() and ProcessMRMLEvents() to bring that state change BACK into the GUI.

Removing observers: In RemoveGUIObservers, make sure you remove every observer you've added to widgets in the GUI before calling Delete() on your widget. Make sure you call SetAndObserveMRML() and SetAndObserveLogic( ) with NULL pointers in your GUI class destructor to remove all observers on MRML and Logic that you have created.

Defining your own widgets: The framework for doing this is still evolving. Currently there are two types of new widgets, those defined as extensions to vtkKW (like vtkKWWindowLevelThresholdEditor.h/cxx) and those defined as Slicer-specific widgets, (like vtkSlicerSliceControlWidget.h/cxx, derived from the vtkSlicerWidget.h/cxx base class). The Slicer widgets have methods for putting observers on their widget components, Logic and MRML, and processing events as well. Thus GUI classes that instance them do not have to manage events for them if the widgets' methods are used instead.

Undo: Make sure you process those events that mark junctures at which MRML state should be saved for Undo/Redo (using MRML's SaveStateForUndo() method. For an example of they way this method is called, see slicer3/Base/GUI/vtkSlicerSliceControllerWidget.cxx.

GUI Style: Try not to add style elements (like foreground and background color, font, relief, etc.) to the interface you create; let the options database (as set up by the vtkSlicerTheme class) specify the style for you so that all modules appear consistent within the Slicer3 application.

Other files you will have to touch: For now, to add your module to Slicer3, create a new instance of vtkSlicerMyModuleLogic and vtkSlicerMyModuleGUI in Applications/GUI/Slicer3.cxx, and follow the pattern used by the GradientAnisotropicDiffusionFilter module for now, until the framework is developed for Slicer3 to autodetect your module and do the right things. You should also create your own CMakeLists.txt file in your module directory and (follow the example in other Module directories), add your module to Modules/CMakeLists.txt, and to Applications/GUI/CMakeLists.txt.


Return to Slicer3 Interface Design and Usability

Current working questions

Some Current working questions on implementation.

Feature Requests, Resource Requests and Emerging Conventions

We are collecting feature, conventions and resource requests from users and developers. Appropriate entries from Slicer2's bug tracker will be periodically added to this repository also.


Return to TOC

External References

<< Back to Slicer3 main page