1 | // Aseprite Document Library |
2 | // Copyright (C) 2019 Igara Studio S.A. |
3 | // |
4 | // This file is released under the terms of the MIT license. |
5 | // Read LICENSE.txt for more information. |
6 | |
7 | #ifndef DOC_SELECTED_OBJECTS_H_INCLUDED |
8 | #define DOC_SELECTED_OBJECTS_H_INCLUDED |
9 | #pragma once |
10 | |
11 | #include "base/debug.h" |
12 | #include "doc/object.h" |
13 | #include "doc/object_id.h" |
14 | |
15 | #include <set> |
16 | |
17 | namespace doc { |
18 | |
19 | // A set of selected objects (e.g. select set of slices) |
20 | class SelectedObjects { |
21 | public: |
22 | typedef std::set<ObjectId> Set; |
23 | typedef Set::iterator iterator; |
24 | typedef Set::const_iterator const_iterator; |
25 | |
26 | template<typename T> |
27 | class IteratableAs { |
28 | public: |
29 | class IteratorAs { |
30 | public: |
31 | typedef T* value_type; |
32 | typedef std::ptrdiff_t difference_type; |
33 | typedef T** pointer; |
34 | typedef T*& reference; |
35 | typedef std::forward_iterator_tag iterator_category; |
36 | IteratorAs(const const_iterator& it) : m_it(it) { } |
37 | bool operator==(const IteratorAs& other) const { |
38 | return m_it == other.m_it; |
39 | } |
40 | bool operator!=(const IteratorAs& other) const { |
41 | return !operator==(other); |
42 | } |
43 | T* operator*() const { |
44 | return doc::get<T>(*m_it); |
45 | } |
46 | IteratorAs& operator++() { |
47 | ++m_it; |
48 | return *this; |
49 | } |
50 | private: |
51 | const_iterator m_it; |
52 | }; |
53 | |
54 | typedef IteratorAs iterator; |
55 | |
56 | iterator begin() const { return m_begin; } |
57 | iterator end() const { return m_end; } |
58 | |
59 | IteratableAs(const SelectedObjects& objs) |
60 | : m_begin(objs.begin()) |
61 | , m_end(objs.end()) { } |
62 | private: |
63 | IteratorAs m_begin, m_end; |
64 | }; |
65 | |
66 | iterator begin() { return m_set.begin(); } |
67 | iterator end() { return m_set.end(); } |
68 | const_iterator begin() const { return m_set.begin(); } |
69 | const_iterator end() const { return m_set.end(); } |
70 | |
71 | bool empty() const { return m_set.empty(); } |
72 | size_t size() const { return m_set.size(); } |
73 | |
74 | void clear() { |
75 | m_set.clear(); |
76 | } |
77 | |
78 | void insert(const ObjectId id) { |
79 | m_set.insert(id); |
80 | } |
81 | |
82 | bool contains(const ObjectId id) const { |
83 | return (m_set.find(id) != end()); |
84 | } |
85 | |
86 | void erase(const ObjectId id) { |
87 | auto it = m_set.find(id); |
88 | if (it != end()) |
89 | m_set.erase(it); |
90 | } |
91 | |
92 | template<typename T> |
93 | T* frontAs() const { |
94 | ASSERT(!m_set.empty()); |
95 | return doc::get<T>(*m_set.begin()); |
96 | } |
97 | |
98 | template<typename T> |
99 | IteratableAs<T> iterateAs() const { return IteratableAs<T>(*this); } |
100 | |
101 | private: |
102 | Set m_set; |
103 | }; |
104 | |
105 | } // namespace doc |
106 | |
107 | #endif // DOC_SELECTED_OBJECTS_H_INCLUDED |
108 | |