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 PXR_USD_SDF_LIST_EDITOR_PROXY_H
25 #define PXR_USD_SDF_LIST_EDITOR_PROXY_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 
38 #include <functional>
39 #include <memory>
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 std::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  /// Deprecated. Please use \ref GetAppliedItems
299  {
300  return GetAppliedItems();
301  }
302 
303  /// Returns the effective list of items represented by the operations in
304  /// this list op. This function should be used to determine the final list
305  /// of items added instead of looking at the individual explicit, prepended,
306  /// and appended item lists.
307  ///
308  /// This is equivalent to calling ApplyOperations on an empty item vector.
309 
311  {
313  if (_Validate()) {
314  _listEditor->ApplyEditsToList(&result);
315  }
316  return result;
317  }
318 
319  void Add(const value_type& value)
320  {
321  if (_Validate()) {
322  if (!_listEditor->IsOrderedOnly()) {
323  if (_listEditor->IsExplicit()) {
324  _AddOrReplace(SdfListOpTypeExplicit, value);
325  }
326  else {
327  GetDeletedItems().Remove(value);
328  _AddOrReplace(SdfListOpTypeAdded, value);
329  }
330  }
331  }
332  }
333 
334  void Prepend(const value_type& value)
335  {
336  if (_Validate()) {
337  if (!_listEditor->IsOrderedOnly()) {
338  if (_listEditor->IsExplicit()) {
339  _Prepend(SdfListOpTypeExplicit, value);
340  }
341  else {
342  GetDeletedItems().Remove(value);
343  _Prepend(SdfListOpTypePrepended, value);
344  }
345  }
346  }
347  }
348 
349  void Append(const value_type& value)
350  {
351  if (_Validate()) {
352  if (!_listEditor->IsOrderedOnly()) {
353  if (_listEditor->IsExplicit()) {
354  _Append(SdfListOpTypeExplicit, value);
355  }
356  else {
357  GetDeletedItems().Remove(value);
358  _Append(SdfListOpTypeAppended, value);
359  }
360  }
361  }
362  }
363 
364  void Remove(const value_type& value)
365  {
366  if (_Validate()) {
367  if (_listEditor->IsExplicit()) {
368  GetExplicitItems().Remove(value);
369  }
370  else if (!_listEditor->IsOrderedOnly()) {
371  GetAddedItems().Remove(value);
372  GetPrependedItems().Remove(value);
373  GetAppendedItems().Remove(value);
374  _AddIfMissing(SdfListOpTypeDeleted, value);
375  }
376  }
377  }
378 
379  void Erase(const value_type& value)
380  {
381  if (_Validate()) {
382  if (!_listEditor->IsOrderedOnly()) {
383  if (_listEditor->IsExplicit()) {
384  GetExplicitItems().Remove(value);
385  }
386  else {
387  GetAddedItems().Remove(value);
388  GetPrependedItems().Remove(value);
389  GetAppendedItems().Remove(value);
390  }
391  }
392  }
393  }
394 
395  /// Explicit bool conversion operator. A ListEditorProxy object
396  /// converts to \c true iff the list editor is valid, converts to \c false
397  /// otherwise.
398  explicit operator bool() const
399  {
400  return _listEditor && _listEditor->IsValid();
401  }
402 
403 private:
404  bool _Validate()
405  {
406  if (!_listEditor) {
407  return false;
408  }
409 
410  if (IsExpired()) {
411  TF_CODING_ERROR("Accessing expired list editor");
412  return false;
413  }
414  return true;
415  }
416 
417  bool _Validate() const
418  {
419  if (!_listEditor) {
420  return false;
421  }
422 
423  if (IsExpired()) {
424  TF_CODING_ERROR("Accessing expired list editor");
425  return false;
426  }
427  return true;
428  }
429 
430  void _AddIfMissing(SdfListOpType op, const value_type& value)
431  {
432  ListProxy proxy(_listEditor, op);
433  size_t index = proxy.Find(value);
434  if (index == size_t(-1)) {
435  proxy.push_back(value);
436  }
437  }
438 
439  void _AddOrReplace(SdfListOpType op, const value_type& value)
440  {
441  ListProxy proxy(_listEditor, op);
442  size_t index = proxy.Find(value);
443  if (index == size_t(-1)) {
444  proxy.push_back(value);
445  }
446  else if (value != static_cast<value_type>(proxy[index])) {
447  proxy[index] = value;
448  }
449  }
450 
451  void _Prepend(SdfListOpType op, const value_type& value)
452  {
453  ListProxy proxy(_listEditor, op);
454  size_t index = proxy.Find(value);
455  if (index != 0) {
456  if (index != size_t(-1)) {
457  proxy.Erase(index);
458  }
459  proxy.insert(proxy.begin(), value);
460  }
461  }
462 
463  void _Append(SdfListOpType op, const value_type& value)
464  {
465  ListProxy proxy(_listEditor, op);
466  size_t index = proxy.Find(value);
467  if (proxy.empty() || (index != proxy.size()-1)) {
468  if (index != size_t(-1)) {
469  proxy.Erase(index);
470  }
471  proxy.push_back(value);
472  }
473  }
474 
475 private:
476  std::shared_ptr<Sdf_ListEditor<TypePolicy> > _listEditor;
477 
479  template <class T> friend class SdfPyWrapListEditorProxy;
480 };
481 
482 // Cannot get from a VtValue except as the correct type.
483 template <class TP>
485  static Vt_DefaultValueHolder Invoke() = delete;
486 };
487 
489 
490 #endif // PXR_USD_SDF_LIST_EDITOR_PROXY_H
bool IsOrderedOnly() const
std::vector< value_type > value_vector_type
ListProxy GetPrependedItems() const
Returns the items prepended by this list editor.
ListProxy GetAppendedItems() const
Returns the items appended by this list editor.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
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)
**But if you need a result
Definition: thread.h:613
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.
SdfListEditorProxy(const std::shared_ptr< Sdf_ListEditor< TypePolicy > > &listEditor)
Creates a new proxy object backed by the supplied list editor.
void RemoveItemEdits(const value_type &item)
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:545
std::function< hboost::optional< value_type >SdfListOpType, const value_type &)> ApplyCallback
value_vector_type GetAppliedItems() const
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:1441
void Append(const value_type &value)
ListProxy GetAddedItems() const
Returns the items added by this list editor.
GLuint index
Definition: glcorearb.h:786
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
bool HasKeys() const
void Remove(const value_type &value)
Definition: core.h:1131
value_vector_type GetAddedOrExplicitItems() const
Deprecated. Please use GetAppliedItems.
bool CopyItems(const This &other)
static Vt_DefaultValueHolder Invoke()
Definition: value.h:1501
void ReplaceItemEdits(const value_type &oldItem, const value_type &newItem)
SdfListEditorProxy< TypePolicy > This
void Remove(const value_type &value)
Definition: listProxy.h:532
size_t Find(const value_type &value) const
Definition: listProxy.h:519