Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #ifndef XENOLITH_RENDERER_MATERIAL2D_COMPONENTS_SCROLL_MATERIALDATASCROLL_H_
24 : #define XENOLITH_RENDERER_MATERIAL2D_COMPONENTS_SCROLL_MATERIALDATASCROLL_H_
25 :
26 : #include "XL2dScrollView.h"
27 : #include "MaterialDataSource.h"
28 : #include "MaterialSurface.h"
29 : #include "MaterialIconSprite.h"
30 : #include "XLSubscriptionListener.h"
31 :
32 : namespace STAPPLER_VERSIONIZED stappler::xenolith::material2d {
33 :
34 : class DataScroll : public ScrollView {
35 : public:
36 : enum class Request {
37 : Reset,
38 : Update,
39 : Front,
40 : Back,
41 : };
42 :
43 : class Item;
44 : class Handler;
45 : class Loader;
46 :
47 : using ItemMap = Map<DataSource::Id, Rc<Item>>;
48 : using DataMap = Map<DataSource::Id, Value>;
49 :
50 : using HandlerCallback = Function<Rc<Handler> (DataScroll *)>;
51 : using ItemCallback = Function<Rc<Surface> (Item *)>;
52 : using LoaderCallback = Function<Rc<Loader>(Request, const Function<void()> &)>;
53 :
54 20 : virtual ~DataScroll() { }
55 :
56 : virtual bool init(DataSource *dataCategory = nullptr, Layout = Layout::Vertical);
57 :
58 : virtual void onContentSizeDirty() override;
59 : virtual void reset();
60 :
61 : virtual Value save() const override;
62 : virtual void load(const Value &) override;
63 :
64 : virtual const ItemMap &getItems() const;
65 :
66 : virtual void setSource(DataSource *);
67 : virtual DataSource *getSource() const;
68 :
69 : virtual void setLookupLevel(uint32_t level);
70 : virtual uint32_t getLookupLevel() const;
71 :
72 : virtual void setItemsForSubcats(bool value);
73 : virtual bool isItemsForSubcat() const;
74 :
75 : virtual void setCategoryBounds(bool value);
76 : virtual bool hasCategoryBounds() const;
77 :
78 : virtual void setLoaderSize(float);
79 : virtual float getLoaderSize() const;
80 :
81 : virtual void setMinLoadTime(TimeInterval time);
82 : virtual TimeInterval getMinLoadTime() const;
83 :
84 : virtual void setMaxSize(size_t max);
85 : virtual size_t getMaxSize() const;
86 :
87 : virtual void setOriginId(DataSource::Id);
88 : virtual DataSource::Id getOriginId() const;
89 :
90 : public:
91 : // if you need to share some resources with slice loader thread, use this callback
92 : // resources will be retained and released by handler in main thread
93 : virtual void setHandlerCallback(HandlerCallback &&);
94 :
95 : // this callback will be called when scroll tries to load next item in slice
96 : virtual void setItemCallback(ItemCallback &&);
97 :
98 : // you can use custom loader with this callback
99 : virtual void setLoaderCallback(LoaderCallback &&);
100 :
101 : protected:
102 : virtual void onSourceDirty();
103 :
104 : virtual size_t getMaxId() const;
105 : virtual Pair<DataSource *, bool> getSourceCategory(int64_t id);
106 :
107 : protected:
108 : virtual bool requestSlice(DataSource::Id, size_t, Request);
109 :
110 : virtual bool updateSlice();
111 : virtual bool resetSlice();
112 : virtual bool downloadFrontSlice(size_t = 0);
113 : virtual bool downloadBackSlice(size_t = 0);
114 :
115 : virtual void onSliceData(DataMap &, Time, Request);
116 : virtual void onSliceItems(ItemMap &&, Time, Request);
117 :
118 : virtual void updateItems();
119 : virtual Rc<Handler> onHandler();
120 : virtual Rc<Surface> onItemRequest(const ScrollController::Item &, DataSource::Id);
121 : virtual Rc<Loader> onLoaderRequest(Request type);
122 :
123 : virtual void onOverscroll(float delta) override;
124 : virtual void updateIndicatorPosition() override;
125 :
126 : uint32_t _categoryLookupLevel = 0;
127 : bool _itemsForSubcats = false;
128 : bool _categoryDirty = true;
129 : bool _useCategoryBounds = false;
130 :
131 : DataListener<DataSource> *_sourceListener = nullptr;
132 :
133 : Rc<Ref> _dataRef;
134 : HandlerCallback _handlerCallback = nullptr;
135 : ItemCallback _itemCallback = nullptr;
136 : LoaderCallback _loaderCallback = nullptr;
137 :
138 : DataSource::Id _currentSliceStart = DataSource::Id(0);
139 : size_t _currentSliceLen = 0;
140 :
141 : DataSource::Id _sliceOrigin = DataSource::Id(0);
142 :
143 : size_t _sliceMax = 24;
144 : size_t _sliceSize = 0;
145 : size_t _slicesCount = 0;
146 : size_t _itemsCount = 0;
147 :
148 : ItemMap _items;
149 :
150 : Time _invalidateAfter;
151 :
152 : float _savedSize = nan();
153 : float _loaderSize = 48.0f;
154 : TimeInterval _minLoadTime = TimeInterval::milliseconds(600);
155 : };
156 :
157 : class DataScroll::Loader : public Node {
158 : public:
159 20 : virtual ~Loader() { }
160 : virtual bool init(const Function<void()> &);
161 : virtual void onContentSizeDirty() override;
162 :
163 : virtual void onEnter(xenolith::Scene *) override;
164 : virtual void onExit() override;
165 :
166 : protected:
167 : IconSprite *_icon = nullptr;
168 : Function<void()> _callback = nullptr;
169 : };
170 :
171 : class DataScroll::Item : public Ref {
172 : public:
173 800 : virtual ~Item() { }
174 : virtual bool init(Value &&val, Vec2, Size2);
175 :
176 : virtual const Value &getData() const;
177 : virtual Size2 getContentSize() const;
178 : virtual Vec2 getPosition() const;
179 :
180 : virtual void setPosition(Vec2);
181 : virtual void setContentSize(Size2);
182 :
183 : virtual void setId(uint64_t);
184 : virtual uint64_t getId() const;
185 :
186 : virtual void setControllerId(size_t);
187 : virtual size_t getControllerId() const;
188 :
189 : protected:
190 : uint64_t _id = 0;
191 : Size2 _size;
192 : Vec2 _position;
193 : Value _data;
194 : size_t _controllerId = 0;
195 : };
196 :
197 : class DataScroll::Handler : public Ref {
198 : public:
199 : using Request = DataScroll::Request;
200 : using DataMap = DataScroll::DataMap;
201 : using ItemMap = DataScroll::ItemMap;
202 : using Layout = DataScroll::Layout;
203 : using CompleteCallback = Function<void()>;
204 :
205 20 : virtual ~Handler() { }
206 : virtual bool init(DataScroll *);
207 :
208 : virtual void setCompleteCallback(CompleteCallback &&);
209 : virtual const CompleteCallback &getCompleteCallback() const;
210 :
211 : virtual Size2 getContentSize() const;
212 : virtual DataScroll * getScroll() const;
213 :
214 : virtual ItemMap run(Request t, DataMap &&) = 0; // on worker thread
215 :
216 : protected:
217 : Size2 _size;
218 : Layout _layout;
219 : Rc<DataScroll> _scroll;
220 : CompleteCallback _callback;
221 : };
222 :
223 : }
224 :
225 : #endif /* XENOLITH_RENDERER_MATERIAL2D_COMPONENTS_SCROLL_MATERIALDATASCROLL_H_ */
|