mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
386 lines
13 KiB
C++
386 lines
13 KiB
C++
/*=========================================================================
|
|
|
|
Program: ParaView
|
|
Module: vtkSMContextViewProxy.cxx
|
|
|
|
Copyright (c) Kitware, Inc.
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
#include "vtkSMContextViewProxy.h"
|
|
|
|
#include "vtkAxis.h"
|
|
#include "vtkChartLegend.h"
|
|
#include "vtkChartXY.h"
|
|
#include "vtkClientServerStream.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkContextInteractorStyle.h"
|
|
#include "vtkContextScene.h"
|
|
#include "vtkContextView.h"
|
|
#include "vtkErrorCode.h"
|
|
#include "vtkEventForwarderCommand.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkProcessModule.h"
|
|
#include "vtkPVContextView.h"
|
|
#include "vtkPVDataInformation.h"
|
|
#include "vtkPVXMLElement.h"
|
|
#include "vtkRenderWindow.h"
|
|
#include "vtkRenderWindowInteractor.h"
|
|
#include "vtkSMPropertyHelper.h"
|
|
#include "vtkSMSourceProxy.h"
|
|
#include "vtkSMUtilities.h"
|
|
#include "vtkSMViewProxyInteractorHelper.h"
|
|
#include "vtkStructuredData.h"
|
|
#include "vtkWeakPointer.h"
|
|
#include "vtkWindowToImageFilter.h"
|
|
|
|
//****************************************************************************
|
|
|
|
namespace {
|
|
const char* XY_CHART_VIEW = "XYChartView";
|
|
}
|
|
|
|
vtkStandardNewMacro(vtkSMContextViewProxy);
|
|
//----------------------------------------------------------------------------
|
|
vtkSMContextViewProxy::vtkSMContextViewProxy()
|
|
: InteractorHelper()
|
|
{
|
|
this->ChartView = NULL;
|
|
this->SkipPlotableCheck = false;
|
|
this->InteractorHelper->SetViewProxy(this);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSMContextViewProxy::~vtkSMContextViewProxy()
|
|
{
|
|
this->InteractorHelper->SetViewProxy(NULL);
|
|
this->InteractorHelper->CleanupInteractor();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::SetupInteractor(vtkRenderWindowInteractor* iren)
|
|
{
|
|
if (this->GetLocalProcessSupportsInteraction())
|
|
{
|
|
this->CreateVTKObjects();
|
|
vtkPVContextView* pvview = vtkPVContextView::SafeDownCast(
|
|
this->GetClientSideObject());
|
|
|
|
// Remember, these calls end up changing ivars on iren.
|
|
pvview->SetupInteractor(iren);
|
|
this->InteractorHelper->SetupInteractor(pvview->GetInteractor());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkRenderWindowInteractor* vtkSMContextViewProxy::GetInteractor()
|
|
{
|
|
this->CreateVTKObjects();
|
|
vtkPVContextView* pvview = vtkPVContextView::SafeDownCast(
|
|
this->GetClientSideObject());
|
|
return pvview? pvview->GetInteractor() : NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::CreateVTKObjects()
|
|
{
|
|
if (this->ObjectsCreated)
|
|
{
|
|
return;
|
|
}
|
|
this->Superclass::CreateVTKObjects();
|
|
|
|
// If prototype, no need to go thurther...
|
|
if(this->Location == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!this->ObjectsCreated)
|
|
{
|
|
return;
|
|
}
|
|
|
|
vtkPVContextView* pvview = vtkPVContextView::SafeDownCast(
|
|
this->GetClientSideObject());
|
|
this->ChartView = pvview->GetContextView();
|
|
|
|
// if user interacts with the chart, we need to ensure that we set the axis
|
|
// behaviors to "FIXED" so that the user chosen axis ranges are preserved in
|
|
// state files, etc.
|
|
this->GetContextItem()->AddObserver(
|
|
vtkCommand::InteractionEvent, this,
|
|
&vtkSMContextViewProxy::OnInteractionEvent);
|
|
|
|
this->ChartView->GetScene()->AddObserver(
|
|
vtkCommand::LeftButtonReleaseEvent, this,
|
|
&vtkSMContextViewProxy::OnLeftButtonReleaseEvent);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkRenderWindow* vtkSMContextViewProxy::GetRenderWindow()
|
|
{
|
|
return this->ChartView->GetRenderWindow();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkContextView* vtkSMContextViewProxy::GetContextView()
|
|
{
|
|
return this->ChartView;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkAbstractContextItem* vtkSMContextViewProxy::GetContextItem()
|
|
{
|
|
vtkPVContextView* pvview = vtkPVContextView::SafeDownCast(
|
|
this->GetClientSideObject());
|
|
return pvview? pvview->GetContextItem() : NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkImageData* vtkSMContextViewProxy::CaptureWindowInternal(int magnification)
|
|
{
|
|
vtkRenderWindow* window = this->GetRenderWindow();
|
|
|
|
// Offscreen rendering is not functioning properly on the mac.
|
|
// Do not use it.
|
|
#if !defined(__APPLE__)
|
|
int prevOffscreen = window->GetOffScreenRendering();
|
|
|
|
vtkPVContextView* view = vtkPVContextView::SafeDownCast(
|
|
this->GetClientSideObject());
|
|
bool use_offscreen = view->GetUseOffscreenRendering() ||
|
|
view->GetUseOffscreenRenderingForScreenshots();
|
|
window->SetOffScreenRendering(use_offscreen? 1: 0);
|
|
#endif
|
|
|
|
window->SwapBuffersOff();
|
|
|
|
this->StillRender();
|
|
|
|
// This is a hack. The only reason we do this is so that in symmetric-batch
|
|
// mode, when the vtkWindowToImageFilter tries to grab frame buffers on the
|
|
// satellites, it doesn't die. In reality, we shouldn't grab the frame buffers
|
|
// at all on satellites. We still need to call
|
|
// vtkWindowToImageFilter::Update() otherwise we can end up with mismatched
|
|
// renders esp when magnification > 1.
|
|
this->GetContextView()->Render();
|
|
|
|
vtkSmartPointer<vtkWindowToImageFilter> w2i =
|
|
vtkSmartPointer<vtkWindowToImageFilter>::New();
|
|
w2i->SetInput(window);
|
|
w2i->SetMagnification(magnification);
|
|
w2i->ReadFrontBufferOff();
|
|
w2i->ShouldRerenderOff();
|
|
w2i->FixBoundaryOff();
|
|
|
|
// BUG #8715: We go through this indirection since the active connection needs
|
|
// to be set during update since it may request re-renders if magnification >1.
|
|
vtkClientServerStream stream;
|
|
stream << vtkClientServerStream::Invoke
|
|
<< w2i.GetPointer() << "Update"
|
|
<< vtkClientServerStream::End;
|
|
this->ExecuteStream(stream, false, vtkProcessModule::CLIENT);
|
|
|
|
window->SwapBuffersOn();
|
|
#if !defined(__APPLE__)
|
|
window->SetOffScreenRendering(prevOffscreen);
|
|
#endif
|
|
|
|
vtkImageData* capture = vtkImageData::New();
|
|
capture->ShallowCopy(w2i->GetOutput());
|
|
window->Frame();
|
|
return capture;
|
|
}
|
|
|
|
static void update_property(vtkAxis* axis, vtkSMProperty* propMin,
|
|
vtkSMProperty* propMax)
|
|
{
|
|
if (axis && propMin && propMax)
|
|
{
|
|
double range[2];
|
|
axis->GetUnscaledRange(range);
|
|
vtkSMPropertyHelper(propMin).Set(range[0]);
|
|
vtkSMPropertyHelper(propMax).Set(range[1]);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::CopyAxisRangesFromChart()
|
|
{
|
|
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
|
|
if (chartXY)
|
|
{
|
|
update_property(
|
|
chartXY->GetAxis(vtkAxis::LEFT),
|
|
this->GetProperty("LeftAxisRangeMinimum"),
|
|
this->GetProperty("LeftAxisRangeMaximum"));
|
|
update_property(
|
|
chartXY->GetAxis(vtkAxis::BOTTOM),
|
|
this->GetProperty("BottomAxisRangeMinimum"),
|
|
this->GetProperty("BottomAxisRangeMaximum"));
|
|
if (this->GetXMLName() == XY_CHART_VIEW)
|
|
{
|
|
update_property(
|
|
chartXY->GetAxis(vtkAxis::RIGHT),
|
|
this->GetProperty("RightAxisRangeMinimum"),
|
|
this->GetProperty("RightAxisRangeMaximum"));
|
|
update_property(
|
|
chartXY->GetAxis(vtkAxis::TOP),
|
|
this->GetProperty("TopAxisRangeMinimum"),
|
|
this->GetProperty("TopAxisRangeMaximum"));
|
|
}
|
|
// HACK: This overcomes a issue where we mark the chart modified, in Render.
|
|
// We seems to be lacking a mechanism in vtkSMProxy to say "here's the
|
|
// new property value, however it's already set on the server side too,
|
|
// so no need to push it or mark pipelines dirty".
|
|
int prev = this->InMarkModified;
|
|
this->InMarkModified = 1;
|
|
this->UpdateVTKObjects();
|
|
this->InMarkModified = prev;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::OnInteractionEvent()
|
|
{
|
|
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
|
|
if (chartXY)
|
|
{
|
|
// Charts by default update axes ranges as needed. On interaction, we force
|
|
// the chart to preserve the user-selected ranges.
|
|
this->CopyAxisRangesFromChart();
|
|
vtkSMPropertyHelper(this, "LeftAxisUseCustomRange").Set(1);
|
|
vtkSMPropertyHelper(this, "BottomAxisUseCustomRange").Set(1);
|
|
if (this->GetXMLName() == XY_CHART_VIEW)
|
|
{
|
|
vtkSMPropertyHelper(this, "RightAxisUseCustomRange").Set(1);
|
|
vtkSMPropertyHelper(this, "TopAxisUseCustomRange").Set(1);
|
|
}
|
|
this->UpdateVTKObjects();
|
|
this->InvokeEvent(vtkCommand::InteractionEvent);
|
|
|
|
// Note: OnInteractionEvent gets called before this->StillRender() gets called
|
|
// as a consequence of this interaction.
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::OnLeftButtonReleaseEvent()
|
|
{
|
|
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
|
|
if (chartXY)
|
|
{
|
|
int pos[2];
|
|
pos[0] = static_cast<int>(chartXY->GetLegend()->GetPointVector().GetX());
|
|
pos[1] = static_cast<int>(chartXY->GetLegend()->GetPointVector().GetY());
|
|
vtkSMPropertyHelper(this, "LegendPosition", true).Set(pos, 2);
|
|
this->UpdateVTKObjects();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::PostRender(bool interactive)
|
|
{
|
|
// BUG# 14899. Ensure that the axis ranges are up-to-date after each render
|
|
// ensuring that the property has the property values (similar in spirit to
|
|
// the camera properties on the Render View).
|
|
this->CopyAxisRangesFromChart();
|
|
this->Superclass::PostRender(interactive);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::ResetDisplay()
|
|
{
|
|
vtkChartXY *chartXY = vtkChartXY::SafeDownCast(this->GetContextItem());
|
|
if (chartXY)
|
|
{
|
|
// simply unlock all the axes ranges. That results in the chart determine
|
|
// new ranges to use in the Update call.
|
|
vtkSMPropertyHelper(this, "LeftAxisUseCustomRange").Set(0);
|
|
vtkSMPropertyHelper(this, "BottomAxisUseCustomRange").Set(0);
|
|
if (this->GetXMLName() == XY_CHART_VIEW)
|
|
{
|
|
vtkSMPropertyHelper(this, "RightAxisUseCustomRange").Set(0);
|
|
vtkSMPropertyHelper(this, "TopAxisUseCustomRange").Set(0);
|
|
}
|
|
this->UpdateVTKObjects();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkSMContextViewProxy::CanDisplayData(vtkSMSourceProxy* producer, int outputPort)
|
|
{
|
|
if (!this->Superclass::CanDisplayData(producer, outputPort))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (this->SkipPlotableCheck)
|
|
{
|
|
// When SkipPlotableCheck is true, we only rely on the representation to
|
|
// select whether it can accept the data produce by the producer. That check
|
|
// happens in Superclass.
|
|
return true;
|
|
}
|
|
|
|
if (producer->GetHints() &&
|
|
producer->GetHints()->FindNestedElementByName("Plotable"))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
vtkPVDataInformation* dataInfo = producer->GetDataInformation(outputPort);
|
|
if (dataInfo->DataSetTypeIsA("vtkTable"))
|
|
{
|
|
return true;
|
|
}
|
|
// also accept 1D structured datasets.
|
|
if (dataInfo->DataSetTypeIsA("vtkImageData") ||
|
|
dataInfo->DataSetTypeIsA("vtkRectilinearGrid"))
|
|
{
|
|
int extent[6];
|
|
dataInfo->GetExtent(extent);
|
|
int temp[6]={0, 0, 0, 0, 0, 0};
|
|
int dimensionality = vtkStructuredData::GetDataDimension(
|
|
vtkStructuredData::SetExtent(extent, temp));
|
|
if (dimensionality == 1)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkSelection* vtkSMContextViewProxy::GetCurrentSelection()
|
|
{
|
|
vtkPVContextView* pvview = vtkPVContextView::SafeDownCast(
|
|
this->GetClientSideObject());
|
|
return pvview ? pvview->GetSelection() : NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkSMContextViewProxy::ReadXMLAttributes(vtkSMSessionProxyManager* pm, vtkPVXMLElement* element)
|
|
{
|
|
int tmp;
|
|
if (element && element->GetScalarAttribute("skip_plotable_check", &tmp))
|
|
{
|
|
this->SkipPlotableCheck = (tmp == 1);
|
|
}
|
|
|
|
return this->Superclass::ReadXMLAttributes(pm, element);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkSMContextViewProxy::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
}
|