3. Views

A view is used to display graph data

In Tulip base you have two different views : Node link diagram view and Spreadsheet view

View example

If you want, you can download an view example here

Extract archive, go in the directory, modify your PATH environment variable, run make and make install

PATH environment variable must contain the directory where you install you tulip. Here you have an example to modify this variable : export PATH=/home/user/install/tulip/bin:$PATH

All the code of this view is commented inside

How to create a view

If you want to create a new view, you have two things to do :

Implement View interface

First you have to implement View interface

This interface can be separated into three parts :

  • Data part :

    QWidget *construct(QWidget *parent);
    // This function is call by the controller when it want to load this view
    // This function must return a QWidget where we have the view
    void setData(Graph *,DataSet); 
    // This function is called when we load a new graph or when we create a new one
    // In the DataSet you can have nothing when you create a new graph or you can have old data when you load a tlp file
    void getData(Graph **, DataSet *);
    // This function is called when you save your graph
    // You must store the graph and the view data
    voif setGraph(graph *);
    // This function is called when you change the visualized graph in hierarchical view (for example)
    Graph *getGraph();
    	    
  • Interactors part :

    void setInteractors(const std::list<Interactor *> &interactors);
    // This function is call by the controller to give interactors to view
    std::list<Interactor *> getInteractors();
    // This function must return interactors of this view (previously given interactors)
    void setActiveInteractor(Interactor *interactor);
    // This function is call by the controller when an interactor is activate on this view
    	    
  • Display part :

    void draw(); 
    // Call when the graph is modified or by interactors
    void redraw();
    // Mainly call by Qt when a menu is open in front of the view
    // Data is not modified so the view is unchanged
    void init();
    // Call when the graph is modified and when the view need to be completely init and draw
    // For example this function is call when a layout algorithm is running, in NodeLinkDiagramComponent this function call centerView() and draw()
    void createPicture(const std::string &pictureName,int width=0, int height=0);
    // Create a picture of this view and store it in file with pictureName
    	    

Call View plugins macro

The second thing you have to do is register your view with the ViewManager

To do that, you just have to call VIEWPLUGIN macro

VIEWPLUGIN(ViewClassName, "ViewName", "Authors", "Date", "Small View description", "View release");

An other solution : Use AbstractView or GlMainView

If you doesn't want to implement all View function, you can implement a class who inherits of AbstractView class or GlMainView class

  • View : is the main interface without implementation

  • AbstractView : provide a basic implementation of interactor system

  • GlMainView : provide a OpenGl view with overview

AbstractView class

AbstractView class provide a basic implementation of iteractor system, so if you want to use it you don't have to implement functions : setInteractors(...), getInteractors(...), setActiveInteractor(...) and getActiveInteractor(...)

But in your construct(..) function implementation, you have to call AbstractView::construct(...). In addition, AbstractView::contruct(...) function create a QWidget for the view, so you just have to write a code like this :

QWidget *YouViewClass::construct(QWidget *parent) {
  QWidget *widget=GlMainView::construct(parent);
  Qwidget *yourWidget=new QWidget;
  ...
  setCentralWidget(yourWidget);
  return widget;
}
      

In addition, AbstractView provide a system to create a context menu (the menu that appears when you click right mouse button in the view)

In this part you have 3 different functions :

  • buildContextMenu function : here you construct your menu, to do that you add QMenu in contextMenu parameters, for example :

    contextMenu->addMenu(new QMenu("viewMenu"));
              
  • computeContextMenu function : this function is call when the user click on a menu in context menu. In this function you have to threat this action

  • Finaly you have specificEventFilter function : this function is call before all others function if the user move/click the mouse. You have to implement (if you want) your specific mouse mechanism on this function

GlMainView class

GlMainView class provide a OpenGl view with an overview

At default this OpenGl view display the Graph, but you can modify this default system. GlMainView use GlMainWidget system to display graph (see GlMainWidget section for more informations

In your view contruct(...) function you have to call GlMainView::construct(..)

This class implement init(...), draw(...), refresh(...) and createPicture(...) functions

In addition, this class add an hide overview button in contextMenu, but you can add your own menus in context menu (as you do with AbstractView)

GlMainView getData(..) and setData(...)

To implement your own methodes, you have two solution :

  • First method is ok if you want to create a view who display the graph with node/link system, this system use setData and getData of GlMainWidget

  • If you want you own OpenGl visualisation, you must rebuild view in setData and store data in getData

GlMainView with node/link visualisation system

For more simple explanation, we focus initially to getData(...) function

As we said above, the GlMainView use a GlMainWidget to display Graph (and other things if you want), so in getData you have to store GlMainWidget data and, if you want, you can store your own data

To do this you must have a code like this

void YourView::getData(Graph **graph,DataSet *dataSet) {
  dataSet->set<DataSet>("glMainWidgetData",mainWidget->getData());
  dataSet->set<string>("owndata","an example of own data");
  *graph=mainWidget->getGraph();
}
	  

Is very simple

Now we focus on setData(...) function

This function is call by the controler to load (previously stored) data on your view

Like getData function, you have to load data in GlMainWidget class

You must have a code like this

void YourView::setData(Graph *graph, DataSet data){
  DataSet glMainWidgetData;
  string stringData;
  
  //We check if glMainWidgetData exist because getData can be call with empty data set (for example : if you create this view with new graph)
  if(data.exist("glMainWidgetData")
    data.get("glMainWidgetData",glMainWidgetData);
  if(data.exist("owndata")
    data.get("owndata",stringData);
    
  mainWidget->setData(graph,glMainWidgetData);
}
          
GlMainView with more complex visualisation

At this point you can't use getData and setData os glMainWidget

You have to completely reload you view in setData function

Why ? This is simple, setData of GlMainWidget is made to automaticaly create a node/link visualisation

So you have to manually load the data in GlMainWidget

For example if you want a view that show a simple sphere, you can create a code like this :

void YourView::setData(Graph *graph, DataSet data){
  this->graph=graph;
  
  //Create a layer with name "Main" is very important, because GlMainWidget use it
  GlLayer *mainLayer=new GlLayer("Main");
  glMainWidget->getScene()->addLayer(mainLayer);
  
  GlSphere *sphere;
  if(data.exist("spherePosition"){
    Coord position=data.get("spherePosition",position);
    sphere=new GlSphere(position,10.);
  }else{
    sphere=new GlSphere(Coord(0,0,0),10.);
  }
  
  mainLayer->addGlEntity("Sphere",sphere);
}
	  

And if you want to store data of your view, you can do this :

void YourView::getData(Graph **graph,DataSet *data){
  *graph=this->graph;
  data->set<Coord>("spherePosition",spherePosition);
}
	  
Overview system

At default, if you create your view, the overview will display anything because you have to give some informations to overview

You just have to call setObservedView(GlMainWidget *widget,GlSimpleEntity *entity) function

In the overview, you can display only one element (but this element can be a GlComposite) and this element must be store in entity parameter

So if you have you view which inherits of GlMainView class and you want to display the graph on the overview (graph is display at default in GlMainView), you have to enter a line like this in your setData(...) function

overviewWidget->setObservedView(mainWidget,mainWidget->getScene()->getGlGraphComposite());