forked from fnc12/Mitsoko
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTableListAdapter.hpp
313 lines (238 loc) · 11.7 KB
/
TableListAdapter.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
#ifndef __VIPER_TABLE_LIST_ADAPTER_H
#define __VIPER_TABLE_LIST_ADAPTER_H
#include "Util.hpp"
#ifdef __APPLE__
#include <UIKit/UIKit.h>
#else
#include <jni.h>
#endif
#include <map>
#include <memory>
#include <iostream>
#include <functional>
#include <stdexcept>
#include "Disposable.hpp"
namespace Mitsoko {
// using std::cout;
// using std::endl;
struct DataSourceBase {
std::function<int()> getSectionsCountLambda;
virtual int getSectionsCount();
std::function<int(int)> getRowsCountLambda;
virtual int getRowsCount(int section);
std::function<std::string(int,int)> getItemIdLambda;
virtual std::string getItemId(int section,int row);
};
/**
* Data source is a class managed by presenter. Data source has functions analogs
* for *tableView:numberOfRowsInSection:* in **UITableViewDataSource** and *getCount*
* in **android.widget.BaseAdapter**.
* **T** is a data type transfered into adapter. It cal be anything comfortable: either
* pointer to an abstract class inherited by your data type (situation similar to Apple when
* data class implements protocol binds to a row itself as a reference to a protocol instance) or
* a *std::tuple* (or any other POD data type) or even data model itself (this is a non-viper way).
*/
template<class T>
struct DataSource : public DataSourceBase {
typedef T data_type;
typedef DataSource<T> Super;
std::function<data_type(int,int)> getItemLambda;
virtual data_type getItem(int section,int row) throw (std::runtime_error){
if(this->getItemLambda){
return std::move(this->getItemLambda(section,row));
}else{
throw std::runtime_error("getItem not impemented. You have either override getItem or assign getItemLambda to dataSource");
}
};
};
/**
* This is a base ckass for adapter. All adapters are stored as pointers to
* instances of this class.
* Disposable is inherited for image caching callbacks.
*/
struct AdapterBase : public Mitsoko::Disposable{
/**
* UITableViewCellStyle mirror enum. Used in iOS only.
*/
enum class RowStyle{
Default
#ifdef __APPLE__
=UITableViewCellStyleDefault
#endif
,
Value1
#ifdef __APPLE__
=UITableViewCellStyleValue1
#endif
,
Value2
#ifdef __APPLE__
=UITableViewCellStyleValue2
#endif
,
Subtitle
#ifdef __APPLE__
=UITableViewCellStyleSubtitle
#endif
,
};
virtual ~AdapterBase();
/**
* This function should be bound to presenter cause in Viper
* presenters receive event from views.
*/
std::function<void(int,int)> rowSelectedLambda;
#ifdef __ANDROID__
/**
* Adapter stores activity handle (or fragment handle) in android. Actually this is a global pointer to activity or fragement
* that helps obtaining context dunring calling `findViewById`.
* Context is required almost everywhere. This is why it is very important to store a
* pointer to it inside adapter. This value must be assigned manually.
*/
const void *activityHandle = nullptr;
#endif
virtual void onRowSelected(int section,int row);
virtual void onCreateCell(const void *cell,int section,int row)=0;
virtual void onDisplayCell(const void *cell,int section,int row)=0;
virtual void didEndDisplayingCell(const void *cell,int section,int row)=0;
virtual std::string getViewClass(int section,int row)=0;
virtual RowStyle getRowStyle(int section,int row)=0;
virtual double getRowHeight(int section,int row)=0;
/**
* Optional.
*/
std::function<std::string(int)> getHeaderClassLambda;
virtual std::string getHeaderClass(int section);
/**
* Optional.
*/
std::function<double(int)> getHeaderHeightLambda;
virtual double getHeaderHeight(int section);
/**
* Optional.
*/
std::function<void(const void*,int)> onCreateHeaderLambda;
virtual void onCreateHeader(const void *headerHandle,int section);
virtual auto getDataSource()->std::shared_ptr<DataSourceBase> =0;
};
/**
* Adapter is a class which adaptates data from data source to row/cell views.
* You can customize adapters in two ways: either create a subclass and override
* required functions or create Adater<T> instace without inheritance and assign
* appropriate lambdas to it.
*/
template<class T>
struct Adapter : public AdapterBase{
typedef T data_type;
typedef DataSource<data_type> data_source_type;
/**
* Constructor from straight variable is comfortable if dataSource
* is not subclassed but implemented with lambdas. If your dataSource is
* subclassed - use c-stor `Adapter(std::shared_ptr<data_source_type>)`.
*/
Adapter(data_source_type ds):Adapter(std::make_shared<data_source_type>(std::move(ds))){}
/**
* Constructor with smart pointer used if your dataSource inherits from
* DataSource.
*/
Adapter(std::shared_ptr<data_source_type> dsPointer):dataSource(std::move(dsPointer)){}
std::function<void(const void*,int,int,const data_type&)> onCreateCellLambda;
std::function<void(const void*,int,int,const data_type&)> onDisplayCellLambda;
std::function<void(const void*,int,int,const data_type&)> didEndDisplayingCellLambda;
std::function<std::string(int,int,const data_type&)> getViewClassLambda;
std::function<RowStyle(int,int,const data_type&)> getRowStyleLambda;
std::function<double(int,int,const data_type&)> getRowHeightLambda;
virtual void onCreateCell(const void *cellHandle,int section,int row,const data_type &item) throw (std::runtime_error){
if(this->onCreateCellLambda){
this->onCreateCellLambda(cellHandle, section, row, item);
}/*else{
throw std::runtime_error("onCreateCell is not implemented. Either implement it in you adapter subclass or assign onCreateCellLambda to your adapter instance");
}*/
}
virtual void onDisplayCell(const void *cellHandle,int section,int row,const data_type &item){
if(this->onDisplayCellLambda){
this->onDisplayCellLambda(cellHandle, section, row, item);
}
}
virtual void didEndDisplayingCell(const void *cell, int section, int row, const data_type &item){
if(this->didEndDisplayingCellLambda){
this->didEndDisplayingCellLambda(cell, section, row, item);
}
}
virtual RowStyle getRowStyle(int section,int row,const data_type &item){
if(this->getRowStyleLambda){
return this->getRowStyleLambda(section, row, item);
}else{
return AdapterBase::RowStyle::Default;
}
}
virtual std::string getViewClass(int section,int row,const data_type &item) throw (std::runtime_error){
if(this->getViewClassLambda){
return std::move(this->getViewClassLambda(section,row,item));
}else{
throw std::runtime_error("getViewClass is not implemented. Either implement it in you adapter subclass or assign getViewClassLambda to your adapter instance");
}
}
virtual double getRowHeight(int section,int row,const data_type &item){
if(this->getRowHeightLambda){
return getRowHeightLambda(section,row,item);
}else{
return 44;
}
}
virtual void didEndDisplayingCell(const void *cell,int section,int row) override final{
this->didEndDisplayingCell(cell, section, row, this->dataSource->getItem(section,row));
}
virtual double getRowHeight(int section,int row) override{
return this->getRowHeight(section,row,this->dataSource->getItem(section,row));
}
virtual RowStyle getRowStyle(int section,int row) override{
return this->getRowStyle(section,row,this->dataSource->getItem(section,row));
}
virtual std::shared_ptr<DataSourceBase> getDataSource() override final{
return std::dynamic_pointer_cast<DataSourceBase>(this->dataSource);
}
virtual void onCreateCell(const void *cell,int section,int row) override{
this->onCreateCell(cell,section,row,this->dataSource->getItem(section,row));
}
virtual void onDisplayCell(const void *cell,int section,int row) override{
this->onDisplayCell(cell,section,row,this->dataSource->getItem(section,row));
}
virtual std::string getViewClass(int section,int row) override{
return std::move(this->getViewClass(section,row,this->dataSource->getItem(section,row)));
}
protected:
std::shared_ptr<data_source_type> dataSource;
};
/**
* This is a service class used for keeping adapter on core side.
*/
struct TableListAdapter{
typedef std::shared_ptr<AdapterBase> AdapterBasePointer;
typedef const void *AdapterId;
constexpr static AdapterId adapterIdNull=nullptr;
static AdapterId registerAdapter(const void *tableOrListView,AdapterBasePointer adapter,const void *jni=nullptr);
static void didEndDisplayingCell(const void *tableOrListView,const void *cell,int section,int row,const void *jni=nullptr);
static void willDisplayCell(const void *tableOrListView,const void *cell,int section,int row,const void *jni=nullptr);
static void didSelectRow(const void *tableOrListView,int section,int row,const void *jni=nullptr);
static double rowHeight(const void *tableOrListView,int section,int row);
static void cellCreated(const void *tableOrListView,const void *cell,int section,int row,const void *jni=nullptr);
/*** iOS only ***/
static AdapterBase::RowStyle cellStyle(const void *tableOrListView,int section,int row);
static void headerCreated(const void *tableOrListView,const void *header,int section,const void *jni=nullptr);
static double headerHeight(const void *tableOrListView,int section,const void *jni=nullptr);
static std::string headerViewClassName(const void *tableOrListView,int section,const void *jni=nullptr);
static std::string cellClassName(const void *tableOrListView,int section,int row,const void *jni=nullptr);
static std::string rowId(const void *tableOrListView,int section,int row,const void *jni=nullptr);
static int rowsCount(const void *tableOrListView,int section,const void *jni=nullptr);
static int sectionsCount(const void *tableOrListView,const void *jni=nullptr);
#ifdef __ANDROID__
static int getAdapterId(const void *tableOrListView,JNIEnv *java_env);
#endif
protected:
typedef std::map<AdapterId, AdapterBasePointer> AdaptersMap;
static AdaptersMap adaptersMap;
// STATIC_VAR(AdaptersMap, adaptersMap, {});
};
}
#endif /* __VIPER_TABLE_LIST_ADAPTER_H */