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 #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 // 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.
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:1394
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
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool HasKeys() const
static Vt_DefaultValueHolder Invoke()
This function must return an object of type T.
Definition: value.h:1437
void Remove(const value_type &value)
Definition: core.h:1131
value_vector_type GetAddedOrExplicitItems() const
Returns the added or explicitly set items.
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