Commit 7e950328 authored by Sebastien Jourdain's avatar Sebastien Jourdain

Enable collaboration to charts

parent 3763ab87
......@@ -263,6 +263,7 @@ SET (CutMulti_REVERSE_CONNECT TRUE)
#
# Don't want to support for now
# - ComparativeVisPanel
# - LoadSaveStateAnimation: The time get reset by collab
#
##########################################################
......@@ -275,7 +276,7 @@ set (CameraLink_ENABLE_COLLAB TRUE)
set (ColorEditor1_ENABLE_COLLAB TRUE)
set (ColorEditor2_ENABLE_COLLAB TRUE)
set (ColorEditor4_ENABLE_COLLAB TRUE)
set (CompositeSurfaceSelection_ENABLE_COLLAB TRUE) # ===== Still render missing on selection
set (CompositeSurfaceSelection_ENABLE_COLLAB TRUE)
set (Contour_ENABLE_COLLAB TRUE)
set (ContourRange_ENABLE_COLLAB TRUE)
set (CustomFilter_ENABLE_COLLAB TRUE)
......@@ -290,14 +291,13 @@ set (ExTimeseries_ENABLE_COLLAB TRUE)
set (ExTimeseries2_ENABLE_COLLAB TRUE)
set (ExtractBlock_ENABLE_COLLAB TRUE)
set (ExtractLevel_ENABLE_COLLAB TRUE)
set (FindDataDialog_ENABLE_COLLAB TRUE) # ===== Still render missing on selection
set (FindDataDialog_ENABLE_COLLAB TRUE)
set (FFTOverTime_ENABLE_COLLAB TRUE)
set (Flow_ENABLE_COLLAB TRUE)
set (Flow2_ENABLE_COLLAB TRUE)
set (Fractal2D_ENABLE_COLLAB TRUE)
set (GridConnectivity_ENABLE_COLLAB TRUE)
set (LoadSaveStateAnimation_ENABLE_COLLAB TRUE) # ===== The time get reset by collab
set (LoadState_ENABLE_COLLAB TRUE) # ===== Invalid state for collab
set (LoadState_ENABLE_COLLAB TRUE)
set (NormalGlyphs_ENABLE_COLLAB TRUE)
set (ObjectInspectorSphere_ENABLE_COLLAB TRUE)
set (OpenSaveData_ENABLE_COLLAB TRUE)
......
......@@ -173,7 +173,7 @@ message LinkState {
}
}
// Extension MousePointer Event ************************************* [70-73]
// Extension MousePointer Event *************************************** [70-73]
message MousePointer {
......@@ -185,6 +185,16 @@ message MousePointer {
}
}
// Extension ChartViewBounds Event ************************************ [75-76]
message ChartViewBounds {
extend Message {
required uint32 view = 75;
repeated double range = 76;
}
}
// Extension ClientsInformation State ********************************* [80-85]
message ClientsInformation {
......@@ -213,7 +223,8 @@ message ChatMessage {
message QtEvent {
enum QtEventType {
CHAT = 1;
OTHER = 2;
CHART_BOUNDS = 2;
OTHER = 3;
}
extend Message {
......
......@@ -23,16 +23,58 @@
#include "vtkRenderWindow.h"
#include "vtkSMUtilities.h"
#include "vtkWindowToImageFilter.h"
#include "vtkAxis.h"
#include "vtkWeakPointer.h"
#include "vtkNew.h"
#include "vtkEventForwarderCommand.h"
//-----------------------------------------------------------------------------
// Minimal storage class for STL containers etc.
class vtkSMContextViewProxy::Private
{
public:
Private() { }
Private()
{
ViewBounds[0] = ViewBounds[2] = ViewBounds[4] = ViewBounds[6] = 0.0;
ViewBounds[1] = ViewBounds[3] = ViewBounds[5] = ViewBounds[7] = 1.0;
}
~Private()
{
}
{
if(this->Proxy && this->Proxy->GetChart() && this->Forwarder.GetPointer() != NULL)
{
this->Proxy->GetChart()->RemoveObserver(this->Forwarder.GetPointer());
}
}
void AttachCallback(vtkSMContextViewProxy* proxy)
{
this->Forwarder->SetTarget(proxy);
this->Proxy = proxy;
if(this->Proxy && this->Proxy->GetChart())
{
this->Proxy->GetChart()->AddObserver(
vtkChart::UpdateRange, this->Forwarder.GetPointer());
}
}
void UpdateBounds()
{
if(this->Proxy && this->Proxy->GetChart())
{
for(int i=0; i < 4; i++)
{
this->Proxy->GetChart()->GetAxis(i)->GetRange(&this->ViewBounds[i*2]);
}
}
}
public:
double ViewBounds[8];
vtkNew<vtkEventForwarderCommand> Forwarder;
private:
vtkWeakPointer<vtkSMContextViewProxy> Proxy;
};
vtkStandardNewMacro(vtkSMContextViewProxy);
......@@ -75,6 +117,9 @@ void vtkSMContextViewProxy::CreateVTKObjects()
this->Storage = new Private;
this->ChartView = pvview->GetContextView();
// Try to attach viewport listener on chart
this->Storage->AttachCallback(this);
}
//----------------------------------------------------------------------------
......@@ -99,8 +144,21 @@ vtkChart* vtkSMContextViewProxy::GetChart()
//-----------------------------------------------------------------------------
void vtkSMContextViewProxy::ResetDisplay()
{
int previousBehaviour[4];
for(int i=0; i < 4; i++)
{
previousBehaviour[i] = this->GetChart()->GetAxis(i)->GetBehavior();
this->GetChart()->GetAxis(i)->SetBehavior(vtkAxis::AUTO);
}
this->GetChart()->RecalculateBounds();
this->GetChartView()->Render();
// Revert behaviour as it use to be...
for(int i=0; i < 4; i++)
{
this->GetChart()->GetAxis(i)->SetBehavior(previousBehaviour[i]);
}
}
//-----------------------------------------------------------------------------
......@@ -140,3 +198,44 @@ void vtkSMContextViewProxy::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
double* vtkSMContextViewProxy::GetViewBounds()
{
this->Storage->UpdateBounds();
return this->Storage->ViewBounds;
}
//----------------------------------------------------------------------------
void vtkSMContextViewProxy::SetViewBounds(double* bounds)
{
if(this->GetChart())
{
// Disable notification...
this->Storage->Forwarder->SetTarget(NULL);
for(int i=0; i < 4; i++)
{
this->Storage->ViewBounds[i*2] = bounds[i*2];
this->Storage->ViewBounds[i*2+1] = bounds[i*2+1];
this->GetChart()->GetAxis(i)->SetBehavior(vtkAxis::FIXED);
this->GetChart()->GetAxis(i)->SetRange(bounds[i*2], bounds[i*2+1]);
this->GetChart()->GetAxis(i)->RecalculateTickSpacing();
}
// cout << "New bounds: ["
// << this->Storage->ViewBounds[0] << ", " << this->Storage->ViewBounds[1] << ", "
// << this->Storage->ViewBounds[2] << ", " << this->Storage->ViewBounds[3] << ", "
// << this->Storage->ViewBounds[4] << ", " << this->Storage->ViewBounds[5] << ", "
// << this->Storage->ViewBounds[6] << ", " << this->Storage->ViewBounds[7] << "]"
// << endl;
// Do the rendering with the new range
this->StillRender();
this->GetChartView()->Render();
// Bring the notification back
this->Storage->Forwarder->SetTarget(this);
}
}
......@@ -34,6 +34,15 @@ public:
vtkTypeMacro(vtkSMContextViewProxy, vtkSMViewProxy);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Return the bounds of the chart
double* GetViewBounds();
// Description:
// Change the bounds of the current chart and change its behavior to be FIXED
// FIXME: We shouldn't have to change the behavior.
void SetViewBounds(double*);
//BTX
// Description:
// Provides access to the vtk chart view.
......
......@@ -72,11 +72,18 @@ void pqCollaborationBehavior::onServerAdded(pqServer* server)
this->CollaborationManager, SLOT(updateEnabledState()),
Qt::QueuedConnection);
// We attach mouse listener on active change time otherwise when the view
// is just added, the widget is not yet correctly initialized...
QObject::connect( &pqActiveObjects::instance(),
SIGNAL(viewChanged(pqView*)),
this->CollaborationManager, SLOT(attachMouseListenerTo3DViews()),
Qt::UniqueConnection);
QObject::connect( pqApplicationCore::instance()->getServerManagerModel(),
SIGNAL(viewAdded(pqView*)),
this->CollaborationManager, SLOT(attachChartViewBoundsListener(pqView*)),
Qt::UniqueConnection);
}
}
......@@ -95,6 +102,10 @@ void pqCollaborationBehavior::onServerRemoved(pqServer* vtkNotUsed(server))
QObject::disconnect( &pqActiveObjects::instance(),
SIGNAL(viewChanged(pqView*)),
this->CollaborationManager, SLOT(attachMouseListenerTo3DViews()));
QObject::disconnect( pqApplicationCore::instance()->getServerManagerModel(),
SIGNAL(viewAdded(pqView*)),
this->CollaborationManager, SLOT(attachChartViewBoundsListener(pqView*)));
this->CollaborationManager->deleteLater();
this->CollaborationManager = NULL;
}
......
......@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "pqServerManagerModel.h"
#include "pqView.h"
#include "pqQVTKWidget.h"
#include "pqContextView.h"
#include "vtkPVMultiClientsInformation.h"
#include "vtkSMCollaborationManager.h"
#include "vtkSMMessage.h"
......@@ -45,8 +46,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vtkSMSessionClient.h"
#include "vtkSMSession.h"
#include "vtkWeakPointer.h"
#include "vtkSMContextViewProxy.h"
#include "vtkChart.h"
#include "vtkNew.h"
#include <vtkstd/set>
#include <vtkstd/map>
// Qt includes.
#include <QAction>
......@@ -70,6 +75,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//***************************************************************************
// Internal class
//***************************************************************************
struct ChartBounds
{
void SetRange(double* otherRange)
{
for(int i=0;i<8;i++)
{
this->Range[i] = otherRange[i];
}
}
double Range[8];
};
class pqCollaborationManager::pqInternals
{
public:
......@@ -80,6 +98,8 @@ public:
this->CollaborativeTimer.setInterval(100);
QObject::connect(&this->CollaborativeTimer, SIGNAL(timeout()),
this->Owner, SLOT(sendMousePointerLocationToOtherClients()));
QObject::connect(&this->CollaborativeTimer, SIGNAL(timeout()),
this->Owner, SLOT(sendChartViewBoundsToOtherClients()));
this->CollaborativeTimer.start();
}
//-------------------------------------------------
......@@ -155,6 +175,7 @@ public:
vtkSMMessage LastMousePointerPosition;
bool MousePointerLocationUpdated;
bool BroadcastMouseLocation;
vtkstd::map<vtkTypeUInt32, ChartBounds> ContextViewBoundsToShare;
protected:
QPointer<pqServer> Server;
......@@ -205,6 +226,24 @@ void pqCollaborationManager::onClientMessage(vtkSMMessage* msg)
chatMsg = msg->GetExtension(ChatMessage::txt).c_str();
emit triggerChatMessage(userId, chatMsg);
break;
case QtEvent::CHART_BOUNDS:
{
vtkTypeUInt32 viewId = msg->GetExtension(ChartViewBounds::view);
double range[8];
for(int i=0;i<8;i++)
{
range[i] = msg->GetExtension(ChartViewBounds::range, i);
}
vtkSMContextViewProxy* view =
vtkSMContextViewProxy::SafeDownCast(
this->collaborationManager()->GetSession()->GetRemoteObject(
viewId));
if(view)
{
view->SetViewBounds(range);
}
break;
}
case QtEvent::OTHER:
// Custom handling
break;
......@@ -379,8 +418,58 @@ void pqCollaborationManager::attachMouseListenerTo3DViews()
Qt::UniqueConnection);
}
}
//-----------------------------------------------------------------------------
void pqCollaborationManager::attachChartViewBoundsListener(pqView* view)
{
pqContextView* chartView = qobject_cast<pqContextView*>(view);
if(chartView)
{
QObject::connect(chartView, SIGNAL(viewBoundsUpdated(vtkTypeUInt32,double*)),
this, SLOT(onChartViewChange(vtkTypeUInt32,double*)),
Qt::UniqueConnection);
}
}
//-----------------------------------------------------------------------------
void pqCollaborationManager::enableMousePointerSharing(bool enable)
{
this->Internals->BroadcastMouseLocation = enable;
}
//-----------------------------------------------------------------------------
void pqCollaborationManager::onChartViewChange(vtkTypeUInt32 gid, double* bounds)
{
// cout << "set bounds: ["
// << bounds[0] << ", " << bounds[1] << ", "
// << bounds[2] << ", " << bounds[3] << ", "
// << bounds[4] << ", " << bounds[5] << ", "
// << bounds[6] << ", " << bounds[7] << "]"
// << endl;
this->Internals->ContextViewBoundsToShare[gid].SetRange(bounds);
}
//-----------------------------------------------------------------------------
void pqCollaborationManager::sendChartViewBoundsToOtherClients()
{
if(this->Internals->ContextViewBoundsToShare.size() > 0)
{
vtkstd::map<vtkTypeUInt32, ChartBounds>::iterator iter;
iter = this->Internals->ContextViewBoundsToShare.begin();
while(iter != this->Internals->ContextViewBoundsToShare.end())
{
vtkSMMessage msg;
msg.SetExtension(QtEvent::type, QtEvent::CHART_BOUNDS);
msg.SetExtension(ChartViewBounds::view, iter->first);
for(int i=0;i<8;i++)
{
msg.AddExtension(ChartViewBounds::range, iter->second.Range[i]);
}
this->collaborationManager()->SendToOtherClients(&msg);
// Move forward
iter++;
}
// Clean up stack
this->Internals->ContextViewBoundsToShare.clear();
}
}
......@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vtkSMMessageMinimal.h"
#include <QObject>
class vtkObject;
class pqServer;
class pqView;
class pqPipelineSource;
......@@ -112,10 +113,18 @@ public slots:
/// mouse location to the other clients every 100 ms
void sendMousePointerLocationToOtherClients();
/// Method triggered by the internal collaboration Timer.
/// This timer prevent a network overload by only sending the latest
/// modified view location to the other clients every 100 ms
void sendChartViewBoundsToOtherClients();
/// Attach a mouse listener if its a 3D view so we can share that
/// information with other clients
void attachMouseListenerTo3DViews();
/// Attach bounds listener if the given view is a pqContextView
void attachChartViewBoundsListener(pqView*);
/// Enable/disable local mouse pointer location
void enableMousePointerSharing(bool);
......@@ -125,6 +134,9 @@ private slots:
/// to synchronize their state.
void onClientMessage(vtkSMMessage* msg);
/// Called when a chart view has changed is view bounds
void onChartViewChange(vtkTypeUInt32 gid, double* bounds);
/// Show another mouse pointer as overlay to a 3D view.
/// x et y are normalized based on height/2 where 0 is the center of the
/// view.
......
......@@ -62,6 +62,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vtkSMPropertyHelper.h"
#include "vtkCommand.h"
#include "vtkNew.h"
#include "pqQVTKWidget.h"
......@@ -103,6 +104,8 @@ public:
{
delete this->Viewport;
}
vtkNew<vtkEventQtSlotConnect> VTKConnect;
};
//-----------------------------------------------------------------------------
......@@ -119,6 +122,9 @@ pqContextView::pqContextView(
this->Command = command::New(*this);
vtkObject::SafeDownCast(viewProxy->GetClientSideObject())->AddObserver(
vtkCommand::SelectionChangedEvent, this->Command);
this->Internal->VTKConnect->Connect( viewProxy, vtkChart::UpdateRange,
this, SLOT(onViewBoundsChange(vtkObject*,ulong,void*,void*)));
}
//-----------------------------------------------------------------------------
......@@ -469,3 +475,15 @@ void pqContextView::selectionChanged()
emit this->selected(opPort);
}
//-----------------------------------------------------------------------------
void pqContextView::onViewBoundsChange(vtkObject* src,
unsigned long vtkNotUsed(event),
void* vtkNotUsed(method),
void* data)
{
vtkSMContextViewProxy* proxy = vtkSMContextViewProxy::SafeDownCast(src);
if(proxy)
{
emit viewBoundsUpdated(proxy->GetGlobalID(), proxy->GetViewBounds());
}
}
......@@ -33,9 +33,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define __pqContextView_h
#include "pqView.h"
#include "vtkType.h"
class vtkSMContextViewProxy;
class vtkContextView;
class vtkObject;
/// pqContextView is an abstract base class for all charting views based on the
/// VTK context charting library.
......@@ -87,12 +89,20 @@ public:
/// Returns true if data on the given output port can be displayed by this view.
virtual bool canDisplay(pqOutputPort* opPort) const;
signals:
void viewBoundsUpdated(vtkTypeUInt32, double*);
protected slots:
virtual void initializeAfterObjectsCreated();
/// Sets up the interactors correctly.
virtual void initializeInteractors();
/// Called when view bounds dynamically change
/// This will
/// emit viewBoundsUpdated(vtkTypeUInt32 proxyId, double bounds[8]) signal.
virtual void onViewBoundsChange(vtkObject*, unsigned long, void*, void*);
protected:
/// Constructor:
/// \c type :- view type.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment