Data view design

From Emergent

Jump to: navigation, search

This document describes the DataView GUI system.

Contents

Overview

The DataView system is a framework for describing and rendering the display of heterogenous data items. There is generally the following relationship of classes in the overall resulting system:

Data Class <--> DataView Class <--> Graphical Class(es)

Sometimes the DataView class will have no direct corresponding Data class, and is merely used to stand for some element of a complex gui entity, such as a browser window.

Classes

DataView (taBase) classes

This section presents the major classes first, then detailed hierarchies for the major classes. Anything starting with "I" is a mix-in interface class.

IDataLinkClient -- can receive data change/destroy notifications
taOBase
  taDataView -- defines the basic behaviors of a data viewing client
    T3DataView -- for rendering 3D displays of the data; manages a T3Node So object
  DataViewer -- parts in the window viewing hiearchy; manages a IDataViewWidget Qt QWidget-based object
DataViewer (A) -- anything common to all viewer types
    can only assume its gui class is a QWidget
    handles: can create a gui obj, either top level or in another window
    has some virt methods for when its subclass is a top-level window
  ToolBar -- for toolbars
  TopLevelViewer -- for anything that can have its own window
    MainWindowViewer -- for the main window; has stuff only applicable to the main win;
       can contain subordinate viewers, toolbars, and dock wins; widget is iMainDataViewer
       is a top-level window
    DockViewer -- for windows that are dockable
      can be docked in a MainWindowViewer, or standalone (when undocked)
      if standalone, then it can be a top-level window
      when standalone, is in .viewers, else is in the .dockies of a MWV
  FrameViewer (A) -- for principal contained views in main, such as browser, edit,
     and T3 (in taMisc) -- these go in central area, in a splitter or other gui container
    BrowseViewer -- for the tree browser -- contains most of the logic
      tabBrowseViewer -- light subclass specialized for taBase root Browsers
      ClassViewer -- light subclass specialized for Type item roots
    PanelViewer -- for the edit panels (supports recursive splitting)
    T3DataViewer -- for T3 guys -- multiple are put in a tabbed gui control
T3DataView (A)
  T3DataViewPar -- for items that contain other items
    T3DataViewRoot -- special guy that is a visual root

A generic list class is defined for all taDataView objects -- it provides convenience methods for forwarding rendering commands to all the children. All other more strongly-typed list classes are made by subclassing this list and adding the TA_DATAVIEWLISTFUNS macro which provides strongly typed FastEl and SafeEl (typically the only accessors needed.)

taList<taDataView>
  DataView_List
    DataViewer_List
      ToolBar_List
      FrameViewer_List
      TopLevelWindow_List
    T3DataView_List

Gui Interfaces

There are two key gui Interfaces that provide abstraction for the concept of contained gui items that can partipate in the following:

  • parent/child hiearchies
  • selection, including multi-select
  • clipboard operations, such as Copy/Cut/Paste
  • Drag and Drop (DND) operations
  • receive updates, such as name changes
ISelectableHost -- for containers

IDataLinkClient
  ISelectable -- for items

These two interfaces are currently expressed by two different subsystems: the Qt-based TreeView/TreeViewItem system, and the Inventor iT3ViewspaceWidget (a Qt class, actually)/T3Node.

The design of these systems enables seamless interaction between them, enabling, for example, a Copy from a 3D view, and then a Paste into a Tree browser.

Qt Gui classes

IDataViewWidget -- this provides generic shared behavior, regardless of the type of widget being used,
  and is a secondary base class of the root classes below:

QWidget
  iFrameViewer -- gui class for FrameViewer;
    
QDockWidget
  iDockViewer -- gui class for DockViewer; very light subclass; can often be used directly,
       just by adding your own content (see Console)

QToolBar
  iToolBar -- gui class for Toolbars;

QMainWindow
  iMainWindowViewer -- the gui class for MainWindowViewer; has tons of stuff for menus, toolbars, frames, etc.

Main Inventor ("So") classes

ISelectableHost
QWidget
  iT3ViewSpaceWidget -- a widget used to display Inventor nodes
ISelectableItem
SoSeparator
  T3Node -- a visual node in a 3d view
    T3NodePar -- a visual node that can have visually nested subnodes

Construction and Usage Flows

DataView objects support a set of generic methods to control construction of gui widgets and display and update of gui information. The following public methods are used to invoke these actions.

  • Clear -- clears (usually deletes) the gui components; usually prior to re-rendering them, or when making the gui go away while keeping the dataview classes
  • Constr (DataViewer) -- constructs the Qt gui classes
  • BuildAll (T3DataView) -- constructs the subclasses that are part of the hierarchy
  • Render -- (re)build and show everything -- only defined on some top-level classes
  • Reset -- deletes all DataView elements under this one; usually on data destroy, or rebuild of data

The actions above are top-level dispatchers that can be called publicly. A corresponding set of implementation methods is provided that are suitably overridden or derived in subclasses. These methods perform the actual work for the given stage. Some of these methods are invoked in more than one context, for example, Clear_impl is used in both Clear and Reset.


  • Clear_impl (T3DataView) -- deletes the So components
  • CloseWindow_impl (DataViewer) -- deletes the Qt Widget component
  • Constr_impl (DataViewer) -- makes the subcomponents and gui components
  • Render_pre -- called for all objects as a first stage in rendering; usually creates the gui components
  • Render_impl -- called for all objects as the principle stage of rendering
  • Render_post -- called for all objects as a final stage of rendering; may apply saved state information
  • Reset_impl -- called for all objects to reset them (remove their children)

This table shows what impl actions comprise each high level action construct:

  • Clear (T3DataView) -- Clear_impl
  • Clear (DataViewer) -- CloseWindow_impl
  • Constr --Constr_impl
  • Render_pre (TopLevelViewer) -- Render_pre, Constr_impl
  • Render -- Clear_impl,Render_pre, Render_impl, Render_post
  • Reset -- Clear_impl, Reset_impl

The high level actions have guard checks to insure that the impl should actually be performed in the context, for example, insuring that the gui components exist before invoking clears or renders, or skipping the action under some overarching conditions such as loading. Impl methods should never be called directly, but are sometimes the correct method to invoke in a context, such as a Data Changed notification -- in these cases, call the DoAction method with the enum(s) for the methods to dispatch (they are dispatched in the correct order, in the above table.)

Here is a summary of the main activities performed during each stage for the major classes; subclasses that manage children perform the actions descendantly -- constructive actions (Render_xxx) done Inherited-Self-Children, destructive actions (Reset/Clear) done Children-Self-Inherited. The base class had a mechanism for efficiently distributing actions to children (see !DoActionChildren_impl). But Constr_impl is never implicitly sent to children, since typically the parent item needs to do fine-grain construction of its child components in the context of its own Constr_impl routine, and will then typically explicitly invoke these child Constr when it is ready.

Class Clear_impl Constr_impl BuildAll Render_pre Render_impl Render_post Reset_impl
DataViewer delete QWidget create QWidget n/a (typ. not used) (typ. not used) apply view state delete child DataView objs
T3DataView delete So node n/a creates child T3DataViews create So node dataparams -> So nodeparams (typ. not used) (typ nothing)
T3DataViewPar (inh) create child T3DVs (inh) dataparams -> So nodeparams (typ. not used) (typ. not used) delete child T3DVs

The DataChanged system is not relevant to DataViewers because they don't have data objects. For T3DataViews the following actions are invoked on dataviews of objects:

  • ITEM_UPDATED -- Render_impl
  • STRUCT_UPDATE_BEGIN (first one) -- Reset
  • STRUCT_UPDATE_END (last one) -- Reset, BuildAll, Render

Note that DataViewer and descendants are typically not connected directly to a data item, therefore, they do not directly recieve any notifications; most of their content items though (in the various subwindows) are connected to the notify system.

Project MainWindowView Layout

Here's what a std 3-panel project view looks like in terms of classes.

(ixxx classes are usually in ta_qtviewer and other guys are in ta_viewer)

tabBrowseViewer  |  PanelViewer        |  T3DataViewer
 w:iBrowseViewer |   w:iTabViewer      |   w:iT3DataViewer            
                 |    iTabView...      |    i/T3DataViewFrame
                 |     iDataPanelSet.. |     T3DataViewRoot.children
                 |      iDataPanel..   |      T3DataViewPar...
                 |                     |       T3DataView..
                 |                     |        T3Node/Leaf/Parent

Here's the key code sequence that creates it all:

  • Main constr: ta_viewer.cpp:905 -- MainWindowViewer* MainWindowViewer::NewProjectBrowser(taProject* proj)
  • ta_viewer.cpp:1113 -- MainWindowViewer::ConstrFrames_impl() -- just calls Constr_impl on frames and then AddFrameViewer on the resulting widget

Note: Q/iTabBar is the item that gets focus events etc! not the widget.. this should be key for linking tabs..

iDataPanel and Subclasses

The iDataPanel is a QFrame derivative that defines an interface for things that live as one item in a tabbed viewing environment, so they live under a iTabViewer which in turn controls a set of iTabView's which in turn contain iDataPanel derivatives.

  • iDataPanel -- base class (ta_qtviewer.h)
    • iDataPanelFrame -- for data-like items that are viewed under user control
      • iListDataPanel -- for list/group like items that need a tree view (?)
      • iTextDataPanel -- for text display (scripts, etc)
      • iDocDataPanel -- for taDoc items
      • EditDataPanel -- base class for any edit dialog-like data panel -- linked to a taiEditDataHost (see below)
      • iDataTablePanel -- for DataTable (ta_datatable_qtso.h)
      • iMatrixPanel -- for Matrix (ta_matrix_qt.h)
      • iProgramPanelBase -- for Program/Group (ta_program_qt.h)
        • iProgramPanel -- for Program
        • iProgramGroupPanel -- for Program_Group
    • iViewPanelFrame -- for a gui control panel which has more automatic view control
      • iDataTableView_Panel -- for datatable view control panel (ta_datatable_qtso.h)
        • iGridTableView_Panel
        • iGraphTableView_Panel
      • VEWorldViewPanel -- VEWorld (ta_virtenv_qtso.h)
      • NetViewPanel -- Network view (netstru_qtso.h)
    • iDataPanelSetBase -- grouping of data panels -- one further level of org between tabs and actual panels -- this is what is actually under the main middle panel tab
      • iDataPanelSet -- holds iDataPanelFrame guys
      • iViewPanelSet -- holds iViewPanelFrame guys

The creation process goes roughly like this:

  • an iDataPanelSet is created for a given object
  • the taiViewType and derivatives creates subpanel(s) within the iDataPanelSet -- basic case is just an EditDataPanel, but others create specialized sets of panels per the program..

Edit Dialog Types

These are bases for actually generating/managing a "Properties" edit dialog, mostly defined in ta_qtdialog.h

  • taiDataHostBase -- base class for managing the contents of an edit dialog -- inherits QObject and IDataLinkClient -- is NOT the widget -- has a widget() call
    • taiDataHost_impl -- adds the IDataHost interface, seems to manage select edit and some other general purpose stuff
      • taiDataHost -- specific instantiation of the gui appearance of the edit, using a QGridLayout or iFormLayout (expensive and slow -- to be replaced)
        • taiEditDataHost -- final guy for class object -- iterates over members, builds views etc
          • taiSelectEditDataHostBase -- for select edit -- in ta_seledit_qt.h (has further derivatives below that!!)
          • cssiEditDialog -- for css items -- in css/css_qtdialog.h
          • iProgramCtrlDataHost -- for program ctrl panel -- in ta_program_qt.h
          • gpiMultiEditDataHost -- in ta_qtgroup.h
          • gpiArrayEditDataHost -- "
          • DocEditDataHost -- for taDoc items, in ta_qtgroup.h
    • taiStringDataHost -- for an edit dialog of a string field member

Keyboard Navigation Issues

  • main docs: http://doc.trolltech.com/4.3/focus.html http://doc.trolltech.com/4.3/qt.html#Key-enum
  • don't use setTabOrder -- you have to set it for the entire chain -- can't just fix one link of it.
  • all the above frame/edit classes (iDataPanel derivatives, taiEditDataHost & derivatives) have a firstTabFocusWidget() function that returns the widget to focus on, and then they redefine the focusNextPrevChild function to select the appropriate widget -- this is really the way more appropriate function to use -- works like a charm!
Personal tools