ParaView
vtkSMVectorPropertyTemplate.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ParaView
4  Module: $RCSfile$
5 
6  Copyright (c) Kitware, Inc.
7  All rights reserved.
8  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
21 #ifndef vtkSMVectorPropertyTemplate_h
22 #define vtkSMVectorPropertyTemplate_h
23 
24 #include "vtkCommand.h"
25 #include "vtkSMProperty.h"
26 #include "vtkSMProxy.h"
27 #include <algorithm>
28 #include <assert.h>
29 #include <limits>
30 #include <sstream>
31 #include <string>
32 #include <typeinfo>
33 #include <vector>
34 #include <vtkPVXMLElement.h>
35 
36 class vtkSMProperty;
37 
38 namespace
39 {
40 template <class B>
41 B vtkSMVPConvertFromString(const std::string& string_representation)
42 {
43  B value;
44  std::istringstream buffer(string_representation);
45  buffer >> value;
46  return value;
47 }
48 
49 template <>
50 vtkMaybeUnused("not used in non-string specializations")
51  vtkStdString vtkSMVPConvertFromString<vtkStdString>(const std::string& string_representation)
52 {
53  return string_representation;
54 }
55 }
56 
57 template <class T>
59 {
60  vtkSMProperty* Property;
61 
62 public:
63  std::vector<T> Values;
64  std::vector<T> UncheckedValues;
65  std::vector<T> DefaultValues; // Values set in the XML configuration.
68 
69  //---------------------------------------------------------------------------
71  {
72  this->Property = property;
73  this->DefaultsValid = false;
74  this->Initialized = false;
75  }
76 
77  //---------------------------------------------------------------------------
79  {
80  this->DefaultValues.clear();
81  this->DefaultValues.insert(this->DefaultValues.end(), this->Values.begin(), this->Values.end());
82  this->DefaultsValid = true;
83  }
84 
85  //---------------------------------------------------------------------------
86  void SetNumberOfUncheckedElements(unsigned int num)
87  {
88  this->UncheckedValues.resize(num);
89  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
90  }
91 
92  //---------------------------------------------------------------------------
94  {
95  return static_cast<unsigned int>(this->UncheckedValues.size());
96  }
97 
98  //---------------------------------------------------------------------------
99  unsigned int GetNumberOfElements() { return static_cast<unsigned int>(this->Values.size()); }
100 
101  //---------------------------------------------------------------------------
102  void SetNumberOfElements(unsigned int num)
103  {
104  if (num == this->Values.size())
105  {
106  return;
107  }
108  this->Values.resize(num);
109  this->UncheckedValues.resize(num);
110  if (num == 0)
111  {
112  // If num == 0, then we already have the intialized values (so to speak).
113  this->Initialized = true;
114  }
115  else
116  {
117  this->Initialized = false;
118  }
119  this->Property->Modified();
120  }
121 
122  //---------------------------------------------------------------------------
123  T& GetElement(unsigned int idx)
124  {
125  assert(idx < this->Values.size());
126  return this->Values[idx];
127  }
128 
129  //---------------------------------------------------------------------------
130  // seems weird that this idx is "int".
131  T& GetDefaultValue(int idx)
132  {
133  if (idx >= 0 && idx < static_cast<int>(this->DefaultValues.size()))
134  {
135  return this->DefaultValues[idx];
136  }
137 
138  static T empty_value = T();
139  return empty_value;
140  }
141 
142  //---------------------------------------------------------------------------
143  T* GetElements() { return (this->Values.size() > 0) ? &this->Values[0] : NULL; }
144 
145  //---------------------------------------------------------------------------
146  T& GetUncheckedElement(unsigned int idx)
147  {
148  assert(idx < this->UncheckedValues.size());
149  return this->UncheckedValues[idx];
150  }
151 
152  //---------------------------------------------------------------------------
153  void SetUncheckedElement(unsigned int idx, T value)
154  {
155  if (idx >= this->GetNumberOfUncheckedElements())
156  {
157  this->UncheckedValues.resize(idx + 1);
158  }
159 
160  if (this->UncheckedValues[idx] != value)
161  {
162  this->UncheckedValues[idx] = value;
163  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
164  }
165  }
166 
167  //---------------------------------------------------------------------------
168  int SetUncheckedElements(const T* values)
169  {
170  return this->SetUncheckedElements(values, this->GetNumberOfUncheckedElements());
171  }
172 
173  //---------------------------------------------------------------------------
174  int SetUncheckedElements(const T* values, unsigned int numValues)
175  {
176  bool modified = false;
177  unsigned int numArgs = this->GetNumberOfUncheckedElements();
178  if (numArgs != numValues)
179  {
180  this->UncheckedValues.resize(numValues);
181  numArgs = numValues;
182  modified = true;
183  }
184  else
185  {
186  modified = !std::equal(this->UncheckedValues.begin(), this->UncheckedValues.end(), values);
187  }
188 
189  if (!modified)
190  {
191  return 1;
192  }
193 
194  std::copy(values, values + numArgs, this->UncheckedValues.begin());
195 
196  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
197  return 1;
198  }
199 
200  //---------------------------------------------------------------------------
201  int SetElement(unsigned int idx, T value)
202  {
203  unsigned int numElems = this->GetNumberOfElements();
204 
205  if (this->Initialized && idx < numElems && value == this->GetElement(idx))
206  {
207  return 1;
208  }
209 
210  if (idx >= numElems)
211  {
212  this->SetNumberOfElements(idx + 1);
213  }
214  this->Values[idx] = value;
215 
216  // Make sure to initialize BEFORE Modified() is called. Otherwise,
217  // the value would not be pushed.
218  this->Initialized = true;
219  this->Property->Modified();
220  this->ClearUncheckedElements();
221  return 1;
222  }
223 
224  //---------------------------------------------------------------------------
225  int SetElements(const T* values)
226  {
227  return this->SetElements(values, this->GetNumberOfElements());
228  }
229 
230  //---------------------------------------------------------------------------
231  int SetElements(const T* values, unsigned int numValues)
232  {
233  bool modified = false;
234  unsigned int numArgs = this->GetNumberOfElements();
235  if (numArgs != numValues)
236  {
237  this->Values.resize(numValues);
238  this->UncheckedValues.resize(numValues);
239  numArgs = numValues;
240  modified = true;
241  }
242  else
243  {
244  modified = !std::equal(this->Values.begin(), this->Values.end(), values);
245  }
246  if (!modified && this->Initialized)
247  {
248  return 1;
249  }
250 
251  std::copy(values, values + numArgs, this->Values.begin());
252  this->Initialized = true;
253  if (!modified && numValues == 0)
254  {
255  // handle the case when the property didn't have valid values but the new
256  // values don't really change anything. In that case, the property hasn't
257  // really been modified, so skip invoking the event. This keeps Python
258  // trace from ending up with lots of properties such as EdgeBlocks etc for
259  // ExodusIIReader which haven't really changed at all.
260  }
261  else
262  {
263  this->Property->Modified();
264  this->ClearUncheckedElements();
265  }
266  return 1;
267  }
268 
269  //---------------------------------------------------------------------------
271  {
272  if (dsrc && dsrc->Initialized)
273  {
274  bool modified = false;
275 
276  if (this->Values != dsrc->Values)
277  {
278  this->Values = dsrc->Values;
279  modified = true;
280  }
281  // If we were not initialized, we are now modified even if the value
282  // did not change
283  modified = modified || !this->Initialized;
284  this->Initialized = true;
285 
286  if (modified)
287  {
288  this->Property->Modified();
289  }
290 
291  // now copy unchecked values.
292  if (this->UncheckedValues != dsrc->Values)
293  {
294  this->UncheckedValues = dsrc->Values;
295  modified = true;
296  }
297  if (modified)
298  {
299  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
300  }
301  }
302  }
303 
304  //---------------------------------------------------------------------------
306  {
307  if (this->DefaultsValid && this->DefaultValues != this->Values)
308  {
309  this->Values = this->DefaultValues;
310  // Make sure to initialize BEFORE Modified() is called. Otherwise,
311  // the value would not be pushed.
312  this->Initialized = true;
313  this->Property->Modified();
314  this->ClearUncheckedElements();
315  }
316  else if (this->Property->GetRepeatable())
317  {
318  this->Values.clear();
319  this->Initialized = true;
320  this->Property->Modified();
321  this->ClearUncheckedElements();
322  }
323  }
324 
325  //---------------------------------------------------------------------------
327  {
328  if (!element)
329  {
330  return false;
331  }
332 
333  std::vector<T> new_values;
334  unsigned int numElems = element->GetNumberOfNestedElements();
335  for (unsigned int i = 0; i < numElems; i++)
336  {
337  vtkPVXMLElement* current = element->GetNestedElement(i);
338  if (current->GetName() && strcmp(current->GetName(), "Element") == 0)
339  {
340  int index;
341  const char* str_value = current->GetAttribute("value");
342  if (str_value && current->GetScalarAttribute("index", &index) && index >= 0)
343  {
344  if (index <= static_cast<int>(new_values.size()))
345  {
346  new_values.resize(index + 1);
347  }
348 
349  new_values[index] = vtkSMVPConvertFromString<T>(str_value);
350  }
351  }
352  }
353  if (new_values.size() > 0)
354  {
355  this->SetElements(&new_values[0], static_cast<unsigned int>(new_values.size()));
356  }
357  else
358  {
359  this->SetNumberOfElements(0);
360  }
361 
362  return true;
363  }
364 
365  //---------------------------------------------------------------------------
366  void SaveStateValues(vtkPVXMLElement* propertyElement)
367  {
368  unsigned int size = this->GetNumberOfElements();
369  if (size > 0)
370  {
371  propertyElement->AddAttribute("number_of_elements", size);
372  }
373  for (unsigned int i = 0; i < size; i++)
374  {
375  std::ostringstream valueAsString;
376 
377  // set the stream precision to the maximum precision for the data type
378  valueAsString.precision(std::numeric_limits<T>::digits10);
379 
380  valueAsString << this->GetElement(i);
381 
382  vtkPVXMLElement* elementElement = vtkPVXMLElement::New();
383  elementElement->SetName("Element");
384  elementElement->AddAttribute("index", i);
385  elementElement->AddAttribute("value", valueAsString.str().c_str());
386  propertyElement->AddNestedElement(elementElement);
387  elementElement->Delete();
388  }
389  }
390 
391  //---------------------------------------------------------------------------
393  {
394  // copy values to unchecked values
395  this->UncheckedValues = this->Values;
396  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
397  }
398 
399  //---------------------------------------------------------------------------
401  {
402  if (this->Values.size() != this->DefaultValues.size())
403  {
404  return false;
405  }
406 
407  return std::equal(this->Values.begin(), this->Values.end(), this->DefaultValues.begin());
408  }
409 };
410 #endif
411 
412 // VTK-HeaderTest-Exclude: vtkSMVectorPropertyTemplate.h
unsigned int GetNumberOfNestedElements()
Get the number of elements nested in this one.
virtual void Modified()
Overridden to support blocking of modified events.
void AddAttribute(const char *attrName, const char *attrValue)
Given it&#39;s name and value, add an attribute.
void Copy(vtkSMVectorPropertyTemplate< T > *dsrc)
void SetNumberOfElements(unsigned int num)
int GetScalarAttribute(const char *name, int *value)
Get the attribute with the given name converted to a scalar value.
int SetUncheckedElements(const T *values, unsigned int numValues)
static vtkPVXMLElement * New()
int SetElement(unsigned int idx, T value)
void SetUncheckedElement(unsigned int idx, T value)
superclass for all SM properties
void SetNumberOfUncheckedElements(unsigned int num)
virtual int GetRepeatable()
If repeatable, a property can have 1 or more values of the same kind.
const char * GetAttribute(const char *name)
Get the attribute with the given name.
vtkPVXMLElement * GetNestedElement(unsigned int index)
Get the element nested in this one at the given index.
void SaveStateValues(vtkPVXMLElement *propertyElement)
int SetElements(const T *values, unsigned int numValues)
vtkSMVectorPropertyTemplate(vtkSMProperty *property)
bool LoadStateValues(vtkPVXMLElement *element)
virtual char * GetName()
Set/Get the name of the element.
void AddNestedElement(vtkPVXMLElement *element, int setPrent)
Add a sub-element.
This is used by vtkPVXMLParser to represent an XML document starting at the root element.
virtual void SetName(const char *)
Set/Get the name of the element.