HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
listEditorProxy.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef SDF_LISTEDITORPROXY_H
25 #define SDF_LISTEDITORPROXY_H
26 
27 /// \file sdf/listEditorProxy.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/listEditor.h"
31 #include "pxr/usd/sdf/listProxy.h"
33 
34 #include "pxr/base/vt/value.h" // for Vt_DefaultValueFactory
35 
36 #include <hboost/optional.hpp>
37 #include <hboost/shared_ptr.hpp>
38 
39 #include <functional>
40 
42 
43 /// \class SdfListEditorProxy
44 ///
45 /// Represents a set of list editing operations.
46 ///
47 /// An SdfListEditorProxy allows consumers to specify a transformation to be
48 /// applied to a list via a set of list editing operations. Given a starting
49 /// ordered list, it can either replace the result with another ordered list
50 /// or apply a sequence of three operations: deleting keys, then adding keys
51 /// to the end (if they aren't already in the starting list), then reordering
52 /// keys.
53 ///
54 /// The type policy defines the value type that a particular proxy can operate
55 /// on.
56 template <class _TypePolicy>
58 public:
59  typedef _TypePolicy TypePolicy;
63  typedef std::vector<value_type> value_vector_type;
64 
65  // ApplyEdits types.
66  typedef std::function<hboost::optional<value_type>
68 
69  // ModifyEdits types.
70  typedef std::function<hboost::optional<value_type>
72 
73  /// Creates a default proxy object. The object evaluates to \c false in a
74  /// boolean context and all operations on this object have no effect.
76  {
77  }
78 
79  /// Creates a new proxy object backed by the supplied list editor.
81  const hboost::shared_ptr<Sdf_ListEditor<TypePolicy> >& listEditor)
82  : _listEditor(listEditor)
83  {
84  }
85 
86  /// Returns true if the list editor is expired.
87  bool IsExpired() const
88  {
89  if (!_listEditor) {
90  return false;
91  }
92 
93  return _listEditor->IsExpired();
94  }
95 
96  /// Returns \c true if the editor has an explicit list, \c false if
97  /// it has list operations.
98  bool IsExplicit() const
99  {
100  return _Validate() ? _listEditor->IsExplicit() : true;
101  }
102 
103  /// Returns \c true if the editor is not explicit and allows ordering
104  /// only.
105  bool IsOrderedOnly() const
106  {
107  return _Validate() ? _listEditor->IsOrderedOnly() : false;
108  }
109 
110  /// Returns \c true if the editor has an explicit list (even if it's
111  /// empty) or it has any added, prepended, appended, deleted,
112  /// or ordered keys.
113  bool HasKeys() const
114  {
115  return _Validate() ? _listEditor->HasKeys() : true;
116  }
117 
118  /// Apply the edits to \p vec.
120  {
121  if (_Validate()) {
122  _listEditor->ApplyEditsToList(vec, ApplyCallback());
123  }
124  }
125 
126  /// Apply the edits to \p vec. If \p callback is valid then it's called
127  /// for every key in the editor before applying it to \p vec. If the
128  /// returned key is invalid then the key will not be applied. Otherwise
129  /// the returned key is applied, allowing callbacks to perform key
130  /// translation.
131  template <class CB>
132  void ApplyEditsToList(value_vector_type* vec, CB callback) const
133  {
134  if (_Validate()) {
135  _listEditor->ApplyEditsToList(vec, ApplyCallback(callback));
136  }
137  }
138 
139  /// Copies the keys from \p other. This differs from assignment
140  /// because assignment just makes two list editors refer to the
141  /// same lists.
142  ///
143  /// Not all list editors support changing their mode. If the mode
144  /// can't be changed to the mode of \p other then this does nothing
145  /// and returns \c false, otherwise it returns \c true.
146  bool CopyItems(const This& other)
147  {
148  return _Validate() && other._Validate() ?
149  _listEditor->CopyEdits(*other._listEditor) : false;
150  }
151 
152  /// Removes all keys and changes the editor to have list operations.
153  ///
154  /// Not all list editors support changing their mode. If the mode
155  /// can't be changed to the mode of \p other then this does nothing
156  /// and returns \c false, otherwise it returns \c true.
157  bool ClearEdits()
158  {
159  return _Validate() ? _listEditor->ClearEdits() : false;
160  }
161 
162  /// Removes all keys and changes the editor to be explicit.
163  ///
164  /// Not all list editors support changing their mode. If the mode
165  /// can't be changed to the mode of \p other then this does nothing
166  /// and returns \c false, otherwise it returns \c true.
168  {
169  return _Validate() ? _listEditor->ClearEditsAndMakeExplicit() : false;
170  }
171 
172  /// \p callback is called for every key. If the returned key is
173  /// invalid then the key is removed, otherwise it's replaced with the
174  /// returned key.
175  template <class CB>
176  void ModifyItemEdits(CB callback)
177  {
178  if (_Validate()) {
179  _listEditor->ModifyItemEdits(ModifyCallback(callback));
180  }
181  }
182 
183  /// Check if the given item is explicit, added, prepended, appended,
184  /// deleted, or ordered by this editor. If \p onlyAddOrExplicit is
185  /// \c true we only check the added or explicit items.
186  bool ContainsItemEdit(const value_type& item,
187  bool onlyAddOrExplicit = false) const
188  {
189  if (_Validate()) {
190  size_t i;
191 
192  i = GetExplicitItems().Find(item);
193  if (i != size_t(-1)) {
194  return true;
195  }
196 
197  i = GetAddedItems().Find(item);
198  if (i != size_t(-1)) {
199  return true;
200  }
201 
202  i = GetPrependedItems().Find(item);
203  if (i != size_t(-1)) {
204  return true;
205  }
206 
207  i = GetAppendedItems().Find(item);
208  if (i != size_t(-1)) {
209  return true;
210  }
211 
212  if (!onlyAddOrExplicit) {
213  i = GetDeletedItems().Find(item);
214  if (i != size_t(-1)) {
215  return true;
216  }
217 
218  i = GetOrderedItems().Find(item);
219  if (i != size_t(-1)) {
220  return true;
221  }
222  }
223  }
224 
225  return false;
226  }
227 
228  /// Remove all occurrences of the given item, regardless of whether
229  /// the item is explicit, added, prepended, appended, deleted, or ordered.
230  void RemoveItemEdits(const value_type& item)
231  {
232  if (_Validate()) {
233  SdfChangeBlock block;
234 
235  GetExplicitItems().Remove(item);
236  GetAddedItems().Remove(item);
237  GetPrependedItems().Remove(item);
238  GetAppendedItems().Remove(item);
239  GetDeletedItems().Remove(item);
240  GetOrderedItems().Remove(item);
241  }
242  }
243 
244  /// Replace all occurrences of the given item, regardless of
245  /// whether the item is explicit, added, prepended, appended,
246  /// deleted or ordered.
247  void ReplaceItemEdits(const value_type& oldItem, const value_type& newItem)
248  {
249  if (_Validate()) {
250  SdfChangeBlock block;
251 
252  GetExplicitItems().Replace(oldItem, newItem);
253  GetAddedItems().Replace(oldItem, newItem);
254  GetPrependedItems().Replace(oldItem, newItem);
255  GetAppendedItems().Replace(oldItem, newItem);
256  GetDeletedItems().Replace(oldItem, newItem);
257  GetOrderedItems().Replace(oldItem, newItem);
258  }
259  }
260 
261  /// Returns the explicitly set items.
263  {
264  return ListProxy(_listEditor, SdfListOpTypeExplicit);
265  }
266 
267  /// Returns the items added by this list editor
269  {
270  return ListProxy(_listEditor, SdfListOpTypeAdded);
271  }
272 
273  /// Returns the items prepended by this list editor
275  {
276  return ListProxy(_listEditor, SdfListOpTypePrepended);
277  }
278 
279  /// Returns the items appended by this list editor
281  {
282  return ListProxy(_listEditor, SdfListOpTypeAppended);
283  }
284 
285  /// Returns the items deleted by this list editor
287  {
288  return ListProxy(_listEditor, SdfListOpTypeDeleted);
289  }
290 
291  /// Returns the items reordered by this list editor
293  {
294  return ListProxy(_listEditor, SdfListOpTypeOrdered);
295  }
296 
297  /// Returns the added or explicitly set items.
299  {
301  if (_Validate()) {
302  _listEditor->ApplyEditsToList(&result);
303  }
304  return result;
305  }
306 
307  void Add(const value_type& value)
308  {
309  if (_Validate()) {
310  if (!_listEditor->IsOrderedOnly()) {
311  if (_listEditor->IsExplicit()) {
312  _AddOrReplace(SdfListOpTypeExplicit, value);
313  }
314  else {
315  GetDeletedItems().Remove(value);
316  _AddOrReplace(SdfListOpTypeAdded, value);
317  }
318  }
319  }
320  }
321 
322  void Prepend(const value_type& value)
323  {
324  if (_Validate()) {
325  if (!_listEditor->IsOrderedOnly()) {
326  if (_listEditor->IsExplicit()) {
327  _Prepend(SdfListOpTypeExplicit, value);
328  }
329  else {
330  GetDeletedItems().Remove(value);
331  _Prepend(SdfListOpTypePrepended, value);
332  }
333  }
334  }
335  }
336 
337  void Append(const value_type& value)
338  {
339  if (_Validate()) {
340  if (!_listEditor->IsOrderedOnly()) {
341  if (_listEditor->IsExplicit()) {
342  _Append(SdfListOpTypeExplicit, value);
343  }
344  else {
345  GetDeletedItems().Remove(value);
346  _Append(SdfListOpTypeAppended, value);
347  }
348  }
349  }
350  }
351 
352  void Remove(const value_type& value)
353  {
354  if (_Validate()) {
355  if (_listEditor->IsExplicit()) {
356  GetExplicitItems().Remove(value);
357  }
358  else if (!_listEditor->IsOrderedOnly()) {
359  GetAddedItems().Remove(value);
360  GetPrependedItems().Remove(value);
361  GetAppendedItems().Remove(value);
362  _AddIfMissing(SdfListOpTypeDeleted, value);
363  }
364  }
365  }
366 
367  void Erase(const value_type& value)
368  {
369  if (_Validate()) {
370  if (!_listEditor->IsOrderedOnly()) {
371  if (_listEditor->IsExplicit()) {
372  GetExplicitItems().Remove(value);
373  }
374  else {
375  GetAddedItems().Remove(value);
376  GetPrependedItems().Remove(value);
377  GetAppendedItems().Remove(value);
378  }
379  }
380  }
381  }
382 
383  /// Explicit bool conversion operator. A ListEditorProxy object
384  /// converts to \c true iff the list editor is valid, converts to \c false
385  /// otherwise.
386  explicit operator bool() const
387  {
388  return _listEditor && _listEditor->IsValid();
389  }
390 
391 private:
392  bool _Validate()
393  {
394  if (!_listEditor) {
395  return false;
396  }
397 
398  if (IsExpired()) {
399  TF_CODING_ERROR("Accessing expired list editor");
400  return false;
401  }
402  return true;
403  }
404 
405  bool _Validate() const
406  {
407  if (!_listEditor) {
408  return false;
409  }
410 
411  if (IsExpired()) {
412  TF_CODING_ERROR("Accessing expired list editor");
413  return false;
414  }
415  return true;
416  }
417 
418  void _AddIfMissing(SdfListOpType op, const value_type& value)
419  {
420  ListProxy proxy(_listEditor, op);
421  size_t index = proxy.Find(value);
422  if (index == size_t(-1)) {
423  proxy.push_back(value);
424  }
425  }
426 
427  void _AddOrReplace(SdfListOpType op, const value_type& value)
428  {
429  ListProxy proxy(_listEditor, op);
430  size_t index = proxy.Find(value);
431  if (index == size_t(-1)) {
432  proxy.push_back(value);
433  }
434  else if (value != static_cast<value_type>(proxy[index])) {
435  proxy[index] = value;
436  }
437  }
438 
439  void _Prepend(SdfListOpType op, const value_type& value)
440  {
441  ListProxy proxy(_listEditor, op);
442  size_t index = proxy.Find(value);
443  if (index != 0) {
444  if (index != size_t(-1)) {
445  proxy.Erase(index);
446  }
447  proxy.insert(proxy.begin(), value);
448  }
449  }
450 
451  void _Append(SdfListOpType op, const value_type& value)
452  {
453  ListProxy proxy(_listEditor, op);
454  size_t index = proxy.Find(value);
455  if (proxy.empty() || (index != proxy.size()-1)) {
456  if (index != size_t(-1)) {
457  proxy.Erase(index);
458  }
459  proxy.push_back(value);
460  }
461  }
462 
463 private:
464  hboost::shared_ptr<Sdf_ListEditor<TypePolicy> > _listEditor;
465 
467  template <class T> friend class SdfPyWrapListEditorProxy;
468 };
469 
470 // Cannot get from a VtValue except as the correct type.
471 template <class TP>
473  static Vt_DefaultValueHolder Invoke() = delete;
474 };
475 
477 
478 #endif // SDF_LISTEDITORPROXY_H
bool IsOrderedOnly() const
std::vector< value_type > value_vector_type
ListProxy GetPrependedItems() const
Returns the items prepended by this list editor.
GLuint index
Definition: glew.h:1814
ListProxy GetAppendedItems() const
Returns the items appended by this list editor.
ListProxy GetExplicitItems() const
Returns the explicitly set items.
#define TF_CODING_ERROR
void ApplyEditsToList(value_vector_type *vec, CB callback) const
void ModifyItemEdits(CB callback)
bool ContainsItemEdit(const value_type &item, bool onlyAddOrExplicit=false) const
void Prepend(const value_type &value)
void Add(const value_type &value)
uint64 value_type
Definition: GA_PrimCompat.h:29
bool ClearEditsAndMakeExplicit()
void Erase(const value_type &value)
bool IsExplicit() const
ListProxy GetOrderedItems() const
Returns the items reordered by this list editor.
void RemoveItemEdits(const value_type &item)
SdfListEditorProxy(const hboost::shared_ptr< Sdf_ListEditor< TypePolicy > > &listEditor)
Creates a new proxy object backed by the supplied list editor.
SdfListOpType
Definition: listOp.h:47
friend class Sdf_ListEditorProxyAccess
ListProxy GetDeletedItems() const
Returns the items deleted by this list editor.
void ApplyEditsToList(value_vector_type *vec) const
Apply the edits to vec.
void Replace(const value_type &oldValue, const value_type &newValue)
Definition: listProxy.h:485
std::function< hboost::optional< value_type >SdfListOpType, const value_type &)> ApplyCallback
SdfListProxy< TypePolicy > ListProxy
_TypePolicy TypePolicy
std::function< hboost::optional< value_type >const value_type &)> ModifyCallback
bool IsExpired() const
Returns true if the list editor is expired.
TypePolicy::value_type value_type
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1245
void Append(const value_type &value)
ListProxy GetAddedItems() const
Returns the items added by this list editor.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:83
bool HasKeys() const
static Vt_DefaultValueHolder Invoke()
This function must return an object of type T.
Definition: value.h:1184
GLuint64EXT * result
Definition: glew.h:14007
void Remove(const value_type &value)
value_vector_type GetAddedOrExplicitItems() const
Returns the added or explicitly set items.
GLsizei const GLfloat * value
Definition: glew.h:1849
bool CopyItems(const This &other)
void ReplaceItemEdits(const value_type &oldItem, const value_type &newItem)
SdfListEditorProxy< TypePolicy > This
void Remove(const value_type &value)
Definition: listProxy.h:472
size_t Find(const value_type &value) const
Definition: listProxy.h:459