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