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 "vtkPVXMLElement.h"
26 #include "vtkSMProperty.h"
27 #include "vtkSMProxy.h"
28 
29 // clang-format off
30 #include "vtk_doubleconversion.h"
31 #include VTK_DOUBLECONVERSION_HEADER(double-conversion.h)
32 // clang-format on
33 
34 #include <algorithm>
35 #include <cassert>
36 #include <sstream>
37 #include <string>
38 #include <vector>
39 
40 class vtkSMProperty;
41 
42 namespace
43 {
44 
45 template <typename T>
46 std::string AsString(const T& var)
47 {
48  std::ostringstream str;
49  str << var;
50  return str.str();
51 }
52 
53 template <>
54 vtkMaybeUnused("not used in non-double specializations") std::string AsString(const double& var)
55 {
56  char buf[256];
57  const double_conversion::DoubleToStringConverter& converter =
58  double_conversion::DoubleToStringConverter::EcmaScriptConverter();
59  double_conversion::StringBuilder builder(buf, sizeof(buf));
60  builder.Reset();
61  converter.ToShortest(var, &builder);
62  return builder.Finalize();
63 }
64 
65 template <class B>
66 B vtkSMVPConvertFromString(const std::string& string_representation)
67 {
68  B value = B();
69  std::istringstream buffer(string_representation);
70  buffer >> value;
71  return value;
72 }
73 
74 template <>
75 vtkMaybeUnused("not used in non-string specializations") std::string
76  vtkSMVPConvertFromString<std::string>(const std::string& string_representation)
77 {
78  return string_representation;
79 }
80 }
81 
82 template <class T>
84 {
85  vtkSMProperty* Property;
86 
87 public:
88  std::vector<T> Values;
89  std::vector<T> UncheckedValues;
90  std::vector<T> DefaultValues; // Values set in the XML configuration.
93 
94  //---------------------------------------------------------------------------
96  {
97  this->Property = property;
98  this->DefaultsValid = false;
99  this->Initialized = false;
100  }
101 
102  //---------------------------------------------------------------------------
104  {
105  this->DefaultValues.clear();
106  this->DefaultValues.insert(this->DefaultValues.end(), this->Values.begin(), this->Values.end());
107  this->DefaultsValid = true;
108  }
109 
110  //---------------------------------------------------------------------------
111  void SetNumberOfUncheckedElements(unsigned int num)
112  {
113  this->UncheckedValues.resize(num);
114  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
115  }
116 
117  //---------------------------------------------------------------------------
119  {
120  return static_cast<unsigned int>(this->UncheckedValues.size());
121  }
122 
123  //---------------------------------------------------------------------------
124  unsigned int GetNumberOfElements() { return static_cast<unsigned int>(this->Values.size()); }
125 
126  //---------------------------------------------------------------------------
127  void SetNumberOfElements(unsigned int num)
128  {
129  if (num == this->Values.size())
130  {
131  return;
132  }
133  this->Values.resize(num);
134  this->UncheckedValues.resize(num);
135  if (num == 0)
136  {
137  // If num == 0, then we already have the initialized values (so to speak).
138  this->Initialized = true;
139  }
140  else
141  {
142  this->Initialized = false;
143  }
144  this->Property->Modified();
145  }
146 
147  //---------------------------------------------------------------------------
148  T& GetElement(unsigned int idx)
149  {
150  assert(idx < this->Values.size());
151  return this->Values[idx];
152  }
153 
154  //---------------------------------------------------------------------------
155  // seems weird that this idx is "int".
156  T& GetDefaultValue(int idx)
157  {
158  if (idx >= 0 && idx < static_cast<int>(this->DefaultValues.size()))
159  {
160  return this->DefaultValues[idx];
161  }
162 
163  static T empty_value = T();
164  return empty_value;
165  }
166 
167  //---------------------------------------------------------------------------
168  T* GetElements() { return (this->Values.size() > 0) ? &this->Values[0] : NULL; }
169 
170  //---------------------------------------------------------------------------
172  {
173  return (this->UncheckedValues.size() > 0) ? &this->UncheckedValues[0] : NULL;
174  }
175  //---------------------------------------------------------------------------
176  T& GetUncheckedElement(unsigned int idx)
177  {
178  assert(idx < this->UncheckedValues.size());
179  return this->UncheckedValues[idx];
180  }
181 
182  //---------------------------------------------------------------------------
183  void SetUncheckedElement(unsigned int idx, T value)
184  {
185  if (idx >= this->GetNumberOfUncheckedElements())
186  {
187  this->UncheckedValues.resize(idx + 1);
188  }
189 
190  if (this->UncheckedValues[idx] != value)
191  {
192  this->UncheckedValues[idx] = value;
193  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
194  }
195  }
196 
197  //---------------------------------------------------------------------------
198  int SetUncheckedElements(const T* values)
199  {
200  return this->SetUncheckedElements(values, this->GetNumberOfUncheckedElements());
201  }
202 
203  //---------------------------------------------------------------------------
204  int SetUncheckedElements(const T* values, unsigned int numValues)
205  {
206  bool modified = false;
207  unsigned int numArgs = this->GetNumberOfUncheckedElements();
208  if (numArgs != numValues)
209  {
210  this->UncheckedValues.resize(numValues);
211  numArgs = numValues;
212  modified = true;
213  }
214  else
215  {
216  modified = !std::equal(this->UncheckedValues.begin(), this->UncheckedValues.end(), values);
217  }
218 
219  if (!modified)
220  {
221  return 1;
222  }
223 
224  std::copy(values, values + numArgs, this->UncheckedValues.begin());
225 
226  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
227  return 1;
228  }
229 
230  //---------------------------------------------------------------------------
231  int SetElement(unsigned int idx, T value)
232  {
233  unsigned int numElems = this->GetNumberOfElements();
234 
235  if (this->Initialized && idx < numElems && value == this->GetElement(idx))
236  {
237  return 1;
238  }
239 
240  if (idx >= numElems)
241  {
242  this->SetNumberOfElements(idx + 1);
243  }
244  this->Values[idx] = value;
245 
246  // Make sure to initialize BEFORE Modified() is called. Otherwise,
247  // the value would not be pushed.
248  this->Initialized = true;
249  this->Property->Modified();
250  this->ClearUncheckedElements();
251  return 1;
252  }
253 
254  //---------------------------------------------------------------------------
255  int SetElements(const T* values)
256  {
257  return this->SetElements(values, this->GetNumberOfElements());
258  }
259 
260  //---------------------------------------------------------------------------
261  int SetElements(const T* values, unsigned int numValues)
262  {
263  bool modified = false;
264  unsigned int numArgs = this->GetNumberOfElements();
265  if (numArgs != numValues)
266  {
267  this->Values.resize(numValues);
268  this->UncheckedValues.resize(numValues);
269  numArgs = numValues;
270  modified = true;
271  }
272  else
273  {
274  modified = !std::equal(this->Values.begin(), this->Values.end(), values);
275  }
276  if (!modified && this->Initialized)
277  {
278  return 1;
279  }
280 
281  std::copy(values, values + numArgs, this->Values.begin());
282  this->Initialized = true;
283  if (!modified && numValues == 0)
284  {
285  // handle the case when the property didn't have valid values but the new
286  // values don't really change anything. In that case, the property hasn't
287  // really been modified, so skip invoking the event. This keeps Python
288  // trace from ending up with lots of properties such as EdgeBlocks etc for
289  // ExodusIIReader which haven't really changed at all.
290  }
291  else
292  {
293  this->Property->Modified();
294  this->ClearUncheckedElements();
295  }
296  return 1;
297  }
298 
299  //---------------------------------------------------------------------------
300  int AppendUncheckedElements(const T* values, unsigned int numValues)
301  {
302  this->UncheckedValues.insert(std::end(this->UncheckedValues), values, values + numValues);
303  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
304 
305  return 1;
306  }
307 
308  //---------------------------------------------------------------------------
309  int AppendElements(const T* values, unsigned int numValues)
310  {
311  this->Values.insert(std::end(this->Values), values, values + numValues);
312  this->Initialized = true;
313  this->Property->Modified();
314  this->ClearUncheckedElements();
315 
316  return 1;
317  }
318 
319  //---------------------------------------------------------------------------
321  {
322  if (dsrc && dsrc->Initialized)
323  {
324  bool modified = false;
325 
326  if (this->Values != dsrc->Values)
327  {
328  this->Values = dsrc->Values;
329  modified = true;
330  }
331  // If we were not initialized, we are now modified even if the value
332  // did not change
333  modified = modified || !this->Initialized;
334  this->Initialized = true;
335 
336  if (modified)
337  {
338  this->Property->Modified();
339  }
340 
341  // now copy unchecked values.
342  if (this->UncheckedValues != dsrc->Values)
343  {
344  this->UncheckedValues = dsrc->Values;
345  modified = true;
346  }
347  if (modified)
348  {
349  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
350  }
351  }
352  }
353 
354  //---------------------------------------------------------------------------
356  {
357  if (this->DefaultsValid && this->DefaultValues != this->Values)
358  {
359  this->Values = this->DefaultValues;
360  // Make sure to initialize BEFORE Modified() is called. Otherwise,
361  // the value would not be pushed.
362  this->Initialized = true;
363  this->Property->Modified();
364  this->ClearUncheckedElements();
365  }
366  else if (this->Property->GetRepeatable())
367  {
368  this->Values.clear();
369  this->Initialized = true;
370  this->Property->Modified();
371  this->ClearUncheckedElements();
372  }
373  }
374 
375  //---------------------------------------------------------------------------
377  {
378  if (!element)
379  {
380  return false;
381  }
382 
383  std::vector<T> new_values;
384  unsigned int numElems = element->GetNumberOfNestedElements();
385  for (unsigned int i = 0; i < numElems; i++)
386  {
387  vtkPVXMLElement* current = element->GetNestedElement(i);
388  if (current->GetName() && strcmp(current->GetName(), "Element") == 0)
389  {
390  int index;
391  const char* str_value = current->GetAttribute("value");
392  if (str_value && current->GetScalarAttribute("index", &index) && index >= 0)
393  {
394  if (index <= static_cast<int>(new_values.size()))
395  {
396  new_values.resize(index + 1);
397  }
398 
399  new_values[index] = vtkSMVPConvertFromString<T>(str_value);
400  }
401  }
402  }
403  if (new_values.size() > 0)
404  {
405  this->SetElements(&new_values[0], static_cast<unsigned int>(new_values.size()));
406  }
407  else
408  {
409  this->SetNumberOfElements(0);
410  }
411 
412  return true;
413  }
414 
415  //---------------------------------------------------------------------------
416  void SaveStateValues(vtkPVXMLElement* propertyElement)
417  {
418  unsigned int size = this->GetNumberOfElements();
419  if (size > 0)
420  {
421  propertyElement->AddAttribute("number_of_elements", size);
422  }
423 
424  // helps save full precision doubles and floats.
425  for (unsigned int i = 0; i < size; i++)
426  {
427  vtkPVXMLElement* elementElement = vtkPVXMLElement::New();
428  elementElement->SetName("Element");
429  elementElement->AddAttribute("index", i);
430  elementElement->AddAttribute("value", ::AsString(this->GetElement(i)).c_str());
431  propertyElement->AddNestedElement(elementElement);
432  elementElement->Delete();
433  }
434  }
435 
436  //---------------------------------------------------------------------------
438  {
439  // copy values to unchecked values
440  this->UncheckedValues = this->Values;
441  this->Property->InvokeEvent(vtkCommand::UncheckedPropertyModifiedEvent);
442  }
443 
444  //---------------------------------------------------------------------------
446  {
447  if (this->Values.size() != this->DefaultValues.size())
448  {
449  return false;
450  }
451 
452  return std::equal(this->Values.begin(), this->Values.end(), this->DefaultValues.begin());
453  }
454 };
455 #endif
456 
457 // VTK-HeaderTest-Exclude: vtkSMVectorPropertyTemplate.h
unsigned int GetNumberOfNestedElements()
Get the number of elements nested in this one.
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 InvokeEvent(unsigned long event)
int SetElement(unsigned int idx, T value)
void SetUncheckedElement(unsigned int idx, T value)
superclass for all SM properties
void SetNumberOfUncheckedElements(unsigned int num)
void Modified() override
Overridden to support blocking of modified events.
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)
size
int AppendElements(const T *values, unsigned int numValues)
int AppendUncheckedElements(const T *values, unsigned int numValues)
bool LoadStateValues(vtkPVXMLElement *element)
value
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.
#define const
Definition: zconf.h:235
index
virtual void SetName(const char *)
Set/Get the name of the element.
virtual void Delete()