File Index Symbol Index

/*********************************************************************** Author: Zihan Chen (vczh) Licensed under https://github.com/vczh-libraries/License ***********************************************************************/
#ifndef VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_CONTAINER
#define VCZH_REFLECTION_GUITYPEDESCRIPTORBUILDER_CONTAINER
#include "GuiTypeDescriptorBuilder.h"
namespace
vl
{
namespace
reflection
{
namespace
description
{
/*********************************************************************** Enumerable Wrappers ***********************************************************************/
template
<
typename
T
>
class
TypedEnumerator
:
public
Object
,
public
collections
::
IEnumerator
<
T
> {
private
:
Ptr
<
IValueEnumerable
>
enumerable
;
Ptr
<
IValueEnumerator
>
enumerator
;
vint
index
;
T
value
;
public
:
TypedEnumerator
(
Ptr
<
IValueEnumerable
>
_enumerable
,
vint
_index
,
const
T
&
_value
) :enumerable(
_enumerable
) ,index(
_index
) ,value(
_value
) {
enumerator
=
enumerable
-
>
CreateEnumerator
();
vint
current
=-
1
;
while
(
current
++<
index
) {
enumerator
-
>
Next
(); } }
TypedEnumerator
(
Ptr
<
IValueEnumerable
>
_enumerable
) :enumerable(
_enumerable
) ,index(-
1
) {
Reset
(); }
collections
::
IEnumerator
<
T
>*
Clone
()
const
override
{
return
new
TypedEnumerator
<
T
>(
enumerable
,
index
,
value
); }
const
T
&
Current
()
const
override
{
return
value
; }
vint
Index
()
const
override
{
return
index
; }
bool
Next
()
override
{
if
(
enumerator
-
>
Next
()) {
index
++;
value
=
UnboxValue
<
T
>(
enumerator
-
>
GetCurrent
());
return
true
; }
else
{
return
false
; } }
void
Reset
()
override
{
index
=-
1
;
enumerator
=
enumerable
-
>
CreateEnumerator
(); } };
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
/// <returns>The created lazy list.</returns>
/// <typeparam name="T">The expected element type.</typeparam>
/// <param name="value">The reflectable container.</param>
template
<
typename
T
>
collections
::
LazyList
<
T
>
GetLazyList
(
Ptr
<
IValueEnumerable
>
value
) {
return
collections
::
LazyList
<
T
>(
new
TypedEnumerator
<
T
>(
value
)); }
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
/// <returns>The created lazy list.</returns>
/// <typeparam name="T">The expected element type.</typeparam>
/// <param name="value">The reflectable container.</param>
template
<
typename
T
>
collections
::
LazyList
<
T
>
GetLazyList
(
Ptr
<
IValueReadonlyList
>
value
) {
return
collections
::
Range
<
vint
>(
0
,
value
-
>
GetCount
()) .
Select
([value](
vint
i
) {
return
UnboxValue
<
T
>(
value
-
>
Get
(
i
)); }); }
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
/// <returns>The created lazy list.</returns>
/// <typeparam name="T">The expected element type.</typeparam>
/// <param name="value">The reflectable container.</param>
template
<
typename
T
>
collections
::
LazyList
<
T
>
GetLazyList
(
Ptr
<
IValueList
>
value
) {
return
GetLazyList
<
T
>(
Ptr
<
IValueReadonlyList
>(
value
)); }
/// <summary>Convert a reflectable container to a lazy list to the known element type.</summary>
/// <returns>The created lazy list.</returns>
/// <typeparam name="T">The expected element type.</typeparam>
/// <param name="value">The reflectable container.</param>
template
<
typename
T
>
collections
::
LazyList
<
T
>
GetLazyList
(
Ptr
<
IValueObservableList
>
value
) {
return
GetLazyList
<
T
>(
Ptr
<
IValueReadonlyList
>(
value
)); }
/// <summary>Convert a reflectable dictionary to a lazy list to the known element type.</summary>
/// <returns>The created lazy list.</returns>
/// <typeparam name="K">The expected key type.</typeparam>
/// <typeparam name="V">The expected value type.</typeparam>
/// <param name="value">The reflectable dictionary.</param>
template
<
typename
K
,
typename
V
>
collections
::
LazyList
<
collections
::
Pair
<
K
,
V
>>
GetLazyList
(
Ptr
<
IValueReadonlyDictionary
>
value
) {
return
collections
::
Range
<
vint
>(
0
,
value
-
>
GetCount
()) .
Select
([value](
vint
i
) {
return
collections
::
Pair
<
K
,
V
>(
UnboxValue
<
K
>(
value
-
>
GetKeys
()
-
>
Get
(
i
)),
UnboxValue
<
V
>(
value
-
>
GetValues
()
-
>
Get
(
i
))); }); }
/// <summary>Convert a reflectable dictionary to a lazy list to the known element type.</summary>
/// <returns>The created lazy list.</returns>
/// <typeparam name="K">The expected key type.</typeparam>
/// <typeparam name="V">The expected value type.</typeparam>
/// <param name="value">The reflectable dictionary.</param>
template
<
typename
K
,
typename
V
>
collections
::
LazyList
<
collections
::
Pair
<
K
,
V
>>
GetLazyList
(
Ptr
<
IValueDictionary
>
value
) {
return
GetLazyList
<
K
,
V
>(
Ptr
<
IValueReadonlyDictionary
>(
value
)); }
/*********************************************************************** Collection Wrappers ***********************************************************************/
namespace
trait_helper
{
template
<
typename
T
>
struct
RemovePtr
{
typedef
T
Type
; };
template
<
typename
T
>
struct
RemovePtr
<
T
*> {
typedef
T
Type
; };
template
<
typename
T
>
struct
RemovePtr
<
Ptr
<
T
>> {
typedef
T
Type
; }; } #pragma warning(push) #pragma warning(disable:
4250
)
template
<
typename
T
>
class
ValueEnumeratorWrapper
:
public
Object
,
public
virtual
IValueEnumerator
{
protected
:
typedef
typename
trait_helper
::
RemovePtr
<
T
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
T
wrapperPointer
;
public
:
ValueEnumeratorWrapper
(
const
T
&
_wrapperPointer
) :wrapperPointer(
_wrapperPointer
) { }
Value
GetCurrent
()
override
{
return
BoxValue
<
ElementType
>(
wrapperPointer
->Current()); }
vint
GetIndex
()
override
{
return
wrapperPointer
->Index(); }
bool
Next
()
override
{
return
wrapperPointer
->Next(); } };
template
<
typename
T
>
class
ValueEnumerableWrapper
:
public
Object
,
public
virtual
IValueEnumerable
{
protected
:
typedef
typename
trait_helper
::
RemovePtr
<
T
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
T
wrapperPointer
;
public
:
ValueEnumerableWrapper
(
const
T
&
_wrapperPointer
) :wrapperPointer(
_wrapperPointer
) { }
Ptr
<
IValueEnumerator
>
CreateEnumerator
()
override
{
return
new
ValueEnumeratorWrapper
<
Ptr
<
collections
::
IEnumerator
<
ElementType
>>>(
wrapperPointer
->CreateEnumerator()); } };
#define WRAPPER_POINTER this->wrapperPointer
template
<
typename
T
>
class
ValueReadonlyListWrapper
:
public
ValueEnumerableWrapper
<
T
>,
public
virtual
IValueReadonlyList
{
protected
:
typedef
typename
trait_helper
::
RemovePtr
<
T
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
typedef
typename
KeyType
<
ElementType
>::
Type
ElementKeyType
;
public
:
ValueReadonlyListWrapper
(
const
T
&
_wrapperPointer
) :
ValueEnumerableWrapper
<
T
>(
_wrapperPointer
) { }
vint
GetCount
()
override
{ }
Value
Get
(
vint
index
)
override
{ }
bool
Contains
(
const
Value
&
value
)
override
{
ElementKeyType
item
=
UnboxValue
<
ElementKeyType
>(
value
); }
vint
IndexOf
(
const
Value
&
value
)
override
{
ElementKeyType
item
=
UnboxValue
<
ElementKeyType
>(
value
); } };
template
<
typename
T
>
class
ValueListWrapper
:
public
ValueReadonlyListWrapper
<
T
>,
public
virtual
IValueList
{
protected
:
typedef
typename
trait_helper
::
RemovePtr
<
T
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
typedef
typename
KeyType
<
ElementType
>::
Type
ElementKeyType
;
public
:
ValueListWrapper
(
const
T
&
_wrapperPointer
) :
ValueReadonlyListWrapper
<
T
>(
_wrapperPointer
) { }
void
Set
(
vint
index
,
const
Value
&
value
)
override
{
ElementType
item
=
UnboxValue
<
ElementType
>(
value
); }
vint
Add
(
const
Value
&
value
)
override
{
ElementType
item
=
UnboxValue
<
ElementType
>(
value
); }
vint
Insert
(
vint
index
,
const
Value
&
value
)
override
{
ElementType
item
=
UnboxValue
<
ElementType
>(
value
); }
bool
Remove
(
const
Value
&
value
)
override
{
ElementKeyType
item
=
UnboxValue
<
ElementKeyType
>(
value
); }
bool
RemoveAt
(
vint
index
)
override
{ }
void
Clear
()
override
{ } };
template
<
typename
T
,
typename
K
>
class
ValueListWrapper
<
collections
::
Array
<
T
,
K
>*> :
public
ValueReadonlyListWrapper
<
collections
::
Array
<
T
,
K
>*>,
public
virtual
IValueList
{
protected
:
typedef
collections
::
Array
<
T
,
K
>
ContainerType
;
typedef
T
ElementType
;
typedef
K
ElementKeyType
;
public
:
ValueListWrapper
(
collections
::
Array
<
T
,
K
>*
_wrapperPointer
) :
ValueReadonlyListWrapper
<
collections
::
Array
<
T
,
K
>*>(
_wrapperPointer
) { }
void
Set
(
vint
index
,
const
Value
&
value
)
override
{
ElementType
item
=
UnboxValue
<
ElementType
>(
value
); }
vint
Add
(
const
Value
&
value
)
override
{
throw
Exception
(
L"Array doesn't have Add method."
); }
vint
Insert
(
vint
index
,
const
Value
&
value
)
override
{
throw
Exception
(
L"Array doesn't have Insert method."
); }
bool
Remove
(
const
Value
&
value
)
override
{
throw
Exception
(
L"Array doesn't have Remove method."
); }
bool
RemoveAt
(
vint
index
)
override
{
throw
Exception
(
L"Array doesn't have RemoveAt method."
); }
void
Clear
()
override
{
throw
Exception
(
L"Array doesn't have Clear method."
); } };
template
<
typename
T
,
typename
K
>
class
ValueListWrapper
<
collections
::
SortedList
<
T
,
K
>*> :
public
ValueReadonlyListWrapper
<
collections
::
SortedList
<
T
,
K
>*>,
public
virtual
IValueList
{
protected
:
typedef
collections
::
SortedList
<
T
,
K
>
ContainerType
;
typedef
T
ElementType
;
typedef
K
ElementKeyType
;
public
:
ValueListWrapper
(
collections
::
SortedList
<
T
,
K
>*
_wrapperPointer
) :
ValueReadonlyListWrapper
<
collections
::
SortedList
<
T
,
K
>*>(
_wrapperPointer
) { }
void
Set
(
vint
index
,
const
Value
&
value
)
override
{
throw
Exception
(
L"SortedList doesn't have Set method."
); }
vint
Add
(
const
Value
&
value
)
override
{
ElementType
item
=
UnboxValue
<
ElementType
>(
value
); }
vint
Insert
(
vint
index
,
const
Value
&
value
)
override
{
throw
Exception
(
L"SortedList doesn't have Insert method."
); }
bool
Remove
(
const
Value
&
value
)
override
{
ElementKeyType
item
=
UnboxValue
<
ElementKeyType
>(
value
); }
bool
RemoveAt
(
vint
index
)
override
{ }
void
Clear
()
override
{ } };
template
<
typename
T
>
class
ValueObservableListWrapper
:
public
ValueListWrapper
<
T
>,
public
virtual
IValueObservableList
{
public
:
ValueObservableListWrapper
(
const
T
&
_wrapperPointer
) :
ValueListWrapper
<
T
>(
_wrapperPointer
) { } };
#undef WRAPPER_POINTER
template
<
typename
T
>
class
ValueReadonlyDictionaryWrapper
:
public
virtual
Object
,
public
virtual
IValueReadonlyDictionary
{
protected
:
typedef
typename
trait_helper
::
RemovePtr
<
T
>::
Type
ContainerType
;
typedef
typename
ContainerType
::KeyContainer
KeyContainer
;
typedef
typename
ContainerType
::ValueContainer
ValueContainer
;
typedef
typename
KeyContainer
::ElementType
KeyValueType
;
typedef
typename
KeyType
<
KeyValueType
>::
Type
KeyKeyType
;
typedef
typename
ValueContainer
::ElementType
ValueType
;
T
wrapperPointer
;
Ptr
<
IValueReadonlyList
>
keys
;
Ptr
<
IValueReadonlyList
>
values
;
public
:
ValueReadonlyDictionaryWrapper
(
const
T
&
_wrapperPointer
) :wrapperPointer(
_wrapperPointer
) { }
Ptr
<
IValueReadonlyList
>
GetKeys
()
override
{
if
(!
keys
) {
keys
=
new
ValueReadonlyListWrapper
<
const
KeyContainer
*>(&
wrapperPointer
->Keys()); }
return
keys
; }
Ptr
<
IValueReadonlyList
>
GetValues
()
override
{
if
(!
values
) {
values
=
new
ValueReadonlyListWrapper
<
const
ValueContainer
*>(&
wrapperPointer
->Values()); }
return
values
; }
vint
GetCount
()
override
{
return
wrapperPointer
->Count(); }
Value
Get
(
const
Value
&
key
)
override
{
KeyKeyType
item
=
UnboxValue
<
KeyKeyType
>(
key
);
ValueType
result
=
wrapperPointer
->Get(
item
);
return
BoxValue
<
ValueType
>(
result
); } };
#define WRAPPER_POINTER ValueReadonlyDictionaryWrapper<T>::wrapperPointer
#define KEY_VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyValueType
#define VALUE_TYPE typename ValueReadonlyDictionaryWrapper<T>::ValueType
#define KEY_KEY_TYPE typename ValueReadonlyDictionaryWrapper<T>::KeyKeyType
template
<
typename
T
>
class
ValueDictionaryWrapper
:
public
virtual
ValueReadonlyDictionaryWrapper
<
T
>,
public
virtual
IValueDictionary
{
public
:
ValueDictionaryWrapper
(
const
T
&
_wrapperPointer
) :
ValueReadonlyDictionaryWrapper
<
T
>(
_wrapperPointer
) { }
void
Set
(
const
Value
&
key
,
const
Value
&
value
)
override
{ }
bool
Remove
(
const
Value
&
key
)
override
{ }
void
Clear
()
override
{ } };
#undef WRAPPER_POINTER
#undef KEY_VALUE_TYPE
#undef VALUE_TYPE
#undef KEY_KEY_TYPE
#pragma warning(pop)
/*********************************************************************** DetailTypeInfoRetriver<TContainer> ***********************************************************************/
template
<
typename
T
>
struct
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
EnumerableType
> {
typedef
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>
UpLevelRetriver
;
static
const
ITypeInfo
::
Decorator
Decorator
=
UpLevelRetriver
::
Decorator
;
typedef
IValueEnumerable
Type
;
typedef
typename
UpLevelRetriver
::
TempValueType
TempValueType
;
typedef
typename
UpLevelRetriver
::
ResultReferenceType
ResultReferenceType
;
typedef
typename
UpLevelRetriver
::
ResultNonReferenceType
ResultNonReferenceType
;
#ifndef VCZH_DEBUG_NO_REFLECTION
static
Ptr
<
ITypeInfo
>
CreateTypeInfo
(
TypeInfoHint
hint
) {
typedef
typename
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
auto
arrayType
=
MakePtr
<
TypeDescriptorTypeInfo
>(
GetTypeDescriptor
<
IValueEnumerable
>(),
hint
);
auto
genericType
=
MakePtr
<
GenericTypeInfo
>(
arrayType
);
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
ElementType
>::
CreateTypeInfo
());
auto
type
=
MakePtr
<
SharedPtrTypeInfo
>(
genericType
);
return
type
; }
#endif
};
template
<
typename
T
>
struct
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
ReadonlyListType
> {
typedef
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>
UpLevelRetriver
;
static
const
ITypeInfo
::
Decorator
Decorator
=
UpLevelRetriver
::
Decorator
;
typedef
IValueReadonlyList
Type
;
typedef
typename
UpLevelRetriver
::
TempValueType
TempValueType
;
typedef
typename
UpLevelRetriver
::
ResultReferenceType
ResultReferenceType
;
typedef
typename
UpLevelRetriver
::
ResultNonReferenceType
ResultNonReferenceType
;
#ifndef VCZH_DEBUG_NO_REFLECTION
static
Ptr
<
ITypeInfo
>
CreateTypeInfo
(
TypeInfoHint
hint
) {
typedef
typename
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
auto
arrayType
=
MakePtr
<
TypeDescriptorTypeInfo
>(
GetTypeDescriptor
<
IValueReadonlyList
>(),
hint
);
auto
genericType
=
MakePtr
<
GenericTypeInfo
>(
arrayType
);
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
ElementType
>::
CreateTypeInfo
());
auto
type
=
MakePtr
<
SharedPtrTypeInfo
>(
genericType
);
return
type
; }
#endif
};
template
<
typename
T
>
struct
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
ListType
> {
typedef
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>
UpLevelRetriver
;
static
const
ITypeInfo
::
Decorator
Decorator
=
UpLevelRetriver
::
Decorator
;
typedef
IValueList
Type
;
typedef
typename
UpLevelRetriver
::
TempValueType
TempValueType
;
typedef
typename
UpLevelRetriver
::
ResultReferenceType
ResultReferenceType
;
typedef
typename
UpLevelRetriver
::
ResultNonReferenceType
ResultNonReferenceType
;
#ifndef VCZH_DEBUG_NO_REFLECTION
static
Ptr
<
ITypeInfo
>
CreateTypeInfo
(
TypeInfoHint
hint
) {
typedef
typename
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
auto
arrayType
=
MakePtr
<
TypeDescriptorTypeInfo
>(
GetTypeDescriptor
<
IValueList
>(),
hint
);
auto
genericType
=
MakePtr
<
GenericTypeInfo
>(
arrayType
);
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
ElementType
>::
CreateTypeInfo
());
auto
type
=
MakePtr
<
SharedPtrTypeInfo
>(
genericType
);
return
type
; }
#endif
};
template
<
typename
T
>
struct
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
ObservableListType
> {
typedef
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>
UpLevelRetriver
;
static
const
ITypeInfo
::
Decorator
Decorator
=
UpLevelRetriver
::
Decorator
;
typedef
IValueObservableList
Type
;
typedef
typename
UpLevelRetriver
::
TempValueType
TempValueType
;
typedef
typename
UpLevelRetriver
::
ResultReferenceType
ResultReferenceType
;
typedef
typename
UpLevelRetriver
::
ResultNonReferenceType
ResultNonReferenceType
;
#ifndef VCZH_DEBUG_NO_REFLECTION
static
Ptr
<
ITypeInfo
>
CreateTypeInfo
(
TypeInfoHint
hint
) {
typedef
typename
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>::
Type
ContainerType
;
typedef
typename
ContainerType
::ElementType
ElementType
;
auto
arrayType
=
MakePtr
<
TypeDescriptorTypeInfo
>(
GetTypeDescriptor
<
IValueObservableList
>(),
hint
);
auto
genericType
=
MakePtr
<
GenericTypeInfo
>(
arrayType
);
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
ElementType
>::
CreateTypeInfo
());
auto
type
=
MakePtr
<
SharedPtrTypeInfo
>(
genericType
);
return
type
; }
#endif
};
template
<
typename
T
>
struct
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
ReadonlyDictionaryType
> {
typedef
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>
UpLevelRetriver
;
static
const
ITypeInfo
::
Decorator
Decorator
=
UpLevelRetriver
::
Decorator
;
typedef
IValueReadonlyList
Type
;
typedef
typename
UpLevelRetriver
::
TempValueType
TempValueType
;
typedef
typename
UpLevelRetriver
::
ResultReferenceType
ResultReferenceType
;
typedef
typename
UpLevelRetriver
::
ResultNonReferenceType
ResultNonReferenceType
;
#ifndef VCZH_DEBUG_NO_REFLECTION
static
Ptr
<
ITypeInfo
>
CreateTypeInfo
(
TypeInfoHint
hint
) {
typedef
typename
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>::
Type
ContainerType
;
typedef
typename
ContainerType
::KeyContainer
KeyContainer
;
typedef
typename
ContainerType
::ValueContainer
ValueContainer
;
typedef
typename
KeyContainer
::ElementType
KeyType
;
typedef
typename
ValueContainer
::ElementType
ValueType
;
auto
arrayType
=
MakePtr
<
TypeDescriptorTypeInfo
>(
GetTypeDescriptor
<
IValueReadonlyDictionary
>(),
hint
);
auto
genericType
=
MakePtr
<
GenericTypeInfo
>(
arrayType
);
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
KeyType
>::
CreateTypeInfo
());
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
ValueType
>::
CreateTypeInfo
());
auto
type
=
MakePtr
<
SharedPtrTypeInfo
>(
genericType
);
return
type
; }
#endif
};
template
<
typename
T
>
struct
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
DictionaryType
> {
typedef
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>
UpLevelRetriver
;
static
const
ITypeInfo
::
Decorator
Decorator
=
UpLevelRetriver
::
Decorator
;
typedef
IValueReadonlyList
Type
;
typedef
typename
UpLevelRetriver
::
TempValueType
TempValueType
;
typedef
typename
UpLevelRetriver
::
ResultReferenceType
ResultReferenceType
;
typedef
typename
UpLevelRetriver
::
ResultNonReferenceType
ResultNonReferenceType
;
#ifndef VCZH_DEBUG_NO_REFLECTION
static
Ptr
<
ITypeInfo
>
CreateTypeInfo
(
TypeInfoHint
hint
) {
typedef
typename
DetailTypeInfoRetriver
<
T
,
TypeFlags
::
NonGenericType
>::
Type
ContainerType
;
typedef
typename
ContainerType
::KeyContainer
KeyContainer
;
typedef
typename
ContainerType
::ValueContainer
ValueContainer
;
typedef
typename
KeyContainer
::ElementType
KeyType
;
typedef
typename
ValueContainer
::ElementType
ValueType
;
auto
arrayType
=
MakePtr
<
TypeDescriptorTypeInfo
>(
GetTypeDescriptor
<
IValueDictionary
>(),
hint
);
auto
genericType
=
MakePtr
<
GenericTypeInfo
>(
arrayType
);
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
KeyType
>::
CreateTypeInfo
());
genericType
-
>
AddGenericArgument
(
TypeInfoRetriver
<
ValueType
>::
CreateTypeInfo
());
auto
type
=
MakePtr
<
SharedPtrTypeInfo
>(
genericType
);
return
type
; }
#endif
};
/*********************************************************************** ParameterAccessor<TContainer> ***********************************************************************/
template
<
typename
T
>
struct
ParameterAccessor
<
collections
::
LazyList
<
T
>,
TypeFlags
::
EnumerableType
> {
static
Value
BoxParameter
(
collections
::
LazyList
<
T
>&
object
,
ITypeDescriptor
*
typeDescriptor
) {
Ptr
<
IValueEnumerable
>
result
=
IValueEnumerable
::
Create
(
collections
::
From
(
object
) .Select([](
const
T
&
item
) {
return
BoxValue
<
T
>(
item
); }) );
ITypeDescriptor
*
td
=
nullptr
;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td
=
Description
<
IValueEnumerable
>::
GetAssociatedTypeDescriptor
();
#endif
return
BoxValue
<
Ptr
<
IValueEnumerable
>>(
result
,
td
); }
static
void
UnboxParameter
(
const
Value
&
value
,
collections
::
LazyList
<
T
>&
result
,
ITypeDescriptor
*
typeDescriptor
,
const
WString
&
valueName
) {
typedef
typename
collections
::
LazyList
<
T
>::
ElementType
ElementType
;
Ptr
<
IValueEnumerable
>
listProxy
=
UnboxValue
<
Ptr
<
IValueEnumerable
>>(
value
,
typeDescriptor
,
valueName
);
result
=
GetLazyList
<
T
>(
listProxy
); } };
template
<
typename
T
>
struct
ParameterAccessor
<
T
,
TypeFlags
::
ReadonlyListType
> {
static
Value
BoxParameter
(
T
&
object
,
ITypeDescriptor
*
typeDescriptor
) {
Ptr
<
IValueReadonlyList
>
result
=
new
ValueReadonlyListWrapper
<
T
*>(&
object
);
ITypeDescriptor
*
td
=
nullptr
;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td
=
Description
<
IValueReadonlyList
>::
GetAssociatedTypeDescriptor
();
#endif
return
BoxValue
<
Ptr
<
IValueReadonlyList
>>(
result
,
td
); }
static
void
UnboxParameter
(
const
Value
&
value
,
T
&
result
,
ITypeDescriptor
*
typeDescriptor
,
const
WString
&
valueName
) {
typedef
typename
T
::ElementType
ElementType
;
Ptr
<
IValueReadonlyList
>
listProxy
=
UnboxValue
<
Ptr
<
IValueReadonlyList
>>(
value
,
typeDescriptor
,
valueName
);
collections
::
LazyList
<
ElementType
>
lazyList
=
GetLazyList
<
ElementType
>(
listProxy
);
collections
::
CopyFrom
(
result
,
lazyList
); } };
template
<
typename
T
>
struct
ParameterAccessor
<
T
,
TypeFlags
::
ListType
> {
static
Value
BoxParameter
(
T
&
object
,
ITypeDescriptor
*
typeDescriptor
) {
Ptr
<
IValueList
>
result
=
new
ValueListWrapper
<
T
*>(&
object
);
ITypeDescriptor
*
td
=
nullptr
;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td
=
Description
<
IValueList
>::
GetAssociatedTypeDescriptor
();
#endif
return
BoxValue
<
Ptr
<
IValueList
>>(
result
,
td
); }
static
void
UnboxParameter
(
const
Value
&
value
,
T
&
result
,
ITypeDescriptor
*
typeDescriptor
,
const
WString
&
valueName
) {
typedef
typename
T
::ElementType
ElementType
;
Ptr
<
IValueList
>
listProxy
=
UnboxValue
<
Ptr
<
IValueList
>>(
value
,
typeDescriptor
,
valueName
);
collections
::
LazyList
<
ElementType
>
lazyList
=
GetLazyList
<
ElementType
>(
listProxy
);
collections
::
CopyFrom
(
result
,
lazyList
); } };
template
<
typename
T
>
struct
ParameterAccessor
<
collections
::
ObservableList
<
T
>,
TypeFlags
::
ObservableListType
> {
static
Value
BoxParameter
(
collections
::
ObservableList
<
T
>&
object
,
ITypeDescriptor
*
typeDescriptor
) {
ITypeDescriptor
*
td
=
nullptr
;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td
=
Description
<
IValueObservableList
>::
GetAssociatedTypeDescriptor
();
#endif
return
BoxValue
<
Ptr
<
IValueObservableList
>>(
object
.
GetWrapper
(),
td
); } };
template
<
typename
T
>
struct
ParameterAccessor
<
T
,
TypeFlags
::
ReadonlyDictionaryType
> {
static
Value
BoxParameter
(
T
&
object
,
ITypeDescriptor
*
typeDescriptor
) {
Ptr
<
IValueReadonlyDictionary
>
result
=
new
ValueReadonlyDictionaryWrapper
<
T
*>(&
object
);
ITypeDescriptor
*
td
=
nullptr
;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td
=
Description
<
IValueReadonlyDictionary
>::
GetAssociatedTypeDescriptor
();
#endif
return
BoxValue
<
Ptr
<
IValueReadonlyDictionary
>>(
result
,
td
); }
static
void
UnboxParameter
(
const
Value
&
value
,
T
&
result
,
ITypeDescriptor
*
typeDescriptor
,
const
WString
&
valueName
) {
typedef
typename
T
::KeyContainer
KeyContainer
;
typedef
typename
T
::ValueContainer
ValueContainer
;
typedef
typename
KeyContainer
::ElementType
KeyType
;
typedef
typename
ValueContainer
::ElementType
ValueType
;
Ptr
<
IValueReadonlyDictionary
>
dictionaryProxy
=
UnboxValue
<
Ptr
<
IValueReadonlyDictionary
>>(
value
,
typeDescriptor
,
valueName
);
collections
::
LazyList
<
collections
::
Pair
<
KeyType
,
ValueType
>>
lazyList
=
GetLazyList
<
KeyType
,
ValueType
>(
dictionaryProxy
);
collections
::
CopyFrom
(
result
,
lazyList
); } };
template
<
typename
T
>
struct
ParameterAccessor
<
T
,
TypeFlags
::
DictionaryType
> {
static
Value
BoxParameter
(
T
&
object
,
ITypeDescriptor
*
typeDescriptor
) {
Ptr
<
IValueDictionary
>
result
=
new
ValueDictionaryWrapper
<
T
*>(&
object
);
ITypeDescriptor
*
td
=
nullptr
;
#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA
td
=
Description
<
IValueDictionary
>::
GetAssociatedTypeDescriptor
();
#endif
return
BoxValue
<
Ptr
<
IValueDictionary
>>(
result
,
td
); }
static
void
UnboxParameter
(
const
Value
&
value
,
T
&
result
,
ITypeDescriptor
*
typeDescriptor
,
const
WString
&
valueName
) {
typedef
typename
T
::KeyContainer
KeyContainer
;
typedef
typename
T
::ValueContainer
ValueContainer
;
typedef
typename
KeyContainer
::ElementType
KeyType
;
typedef
typename
ValueContainer
::ElementType
ValueType
;
Ptr
<
IValueDictionary
>
dictionaryProxy
=
UnboxValue
<
Ptr
<
IValueDictionary
>>(
value
,
typeDescriptor
,
valueName
);
collections
::
LazyList
<
collections
::
Pair
<
KeyType
,
ValueType
>>
lazyList
=
GetLazyList
<
KeyType
,
ValueType
>(
dictionaryProxy
);
collections
::
CopyFrom
(
result
,
lazyList
); } }; } }
namespace
collections
{
/// <summary>Base type of observable container which triggers callbacks whenever items are changed.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements. It is recommended to use the default value.</typeparam>
/// <remarks>
/// <p>Methods are the same to <see cref="List`2"/>, except that operator[] is readonly.</p>
/// <p>
/// When an item is being inserted to the list,
/// <b>QueryInsert</b> will be called to determine if this item can be inserted,
/// <b>BeforeInsert</b> will be called before inserting,
/// <b>AfterInsert</b> will be called after inserting.
/// </p>
/// <p>
/// When an item is being removed from the list,
/// <b>QueryRemove</b> will be called to determine if this item can be removed,
/// <b>BeforeRemove</b> will be called before removing,
/// <b>AfterRemove</b> will be called after removing.
/// </p>
/// <p>
/// When an item is being replaced, it is considered as removing the original item and inserting the new item.
/// </p>
/// <p>
/// After any changing happens, <b>NotifyUpdateInternal</b> is called.
/// Arguments is exactly the same as <see cref="reflection::description::IValueObservableList::ItemChanged"/>.
/// </p>
/// </remarks>
template
<
typename
T
,
typename
K
=
typename
KeyType
<
T
>::
Type
>
class
ObservableListBase
:
public
Object
,
public
virtual
collections
::
IEnumerable
<
T
> {
protected
:
collections
::
List
<
T
,
K
>
items
;
virtual
void
NotifyUpdateInternal
(
vint
start
,
vint
count
,
vint
newCount
) { }
virtual
bool
QueryInsert
(
vint
index
,
const
T
&
value
) {
return
true
; }
virtual
void
BeforeInsert
(
vint
index
,
const
T
&
value
) { }
virtual
void
AfterInsert
(
vint
index
,
const
T
&
value
) { }
virtual
bool
QueryRemove
(
vint
index
,
const
T
&
value
) {
return
true
; }
virtual
void
BeforeRemove
(
vint
index
,
const
T
&
value
) { }
virtual
void
AfterRemove
(
vint
index
,
vint
count
) { }
public
:
ObservableListBase
() { }
~
ObservableListBase
() { }
collections
::
IEnumerator
<
T
>*
CreateEnumerator
()
const
{
return
items
.
CreateEnumerator
(); }
/// <summary>Trigger <b>NotifyUpdateInternal</b> manually.</summary>
/// <returns>Returns true if arguments are not out of range.</returns>
/// <param name="start">The index of the first item that are changed.</param>
/// <param name="count">The number of items that are changed, the default value is 1.</param>
/// <remarks>
/// <p>
/// This is useful when the container is not actually changed, but data in some items are changed.
/// For example, in an observable list of shared pointers,
/// properties of elements are changed does not trigger callbacks because it doesn't change pointers in the list.
/// </p>
/// <p>
/// If subscribers need to know about such change, calling this function is an easy way to do it.
/// </p>
/// </remarks>
bool
NotifyUpdate
(
vint
start
,
vint
count
=
1
) {
if
(
start
<
0
||
start
>=
items
.
Count
() ||
count
<=
0
||
start
+
count
>
items
.
Count
()) {
return
false
; }
else
{
NotifyUpdateInternal
(
start
,
count
,
count
);
return
true
; } }
bool
Contains
(
const
K
&
item
)
const
{
return
items
.
Contains
(
item
); }
vint
Count
()
const
{
return
items
.
Count
(); }
vint
Count
() {
return
items
.
Count
(); }
const
T
&
Get
(
vint
index
)
const
{
return
items
.
Get
(
index
); }
const
T
&
operator
[
]
(
vint
index
)
const
{
return
items
.
Get
(
index
); }
vint
IndexOf
(
const
K
&
item
)
const
{
return
items
.
IndexOf
(
item
); }
vint
Add
(
const
T
&
item
) {
return
Insert
(
items
.
Count
(),
item
); }
bool
Remove
(
const
K
&
item
) {
vint
index
=
items
.
IndexOf
(
item
);
if
(
index
== -
1
)
return
false
;
return
RemoveAt
(
index
); }
bool
RemoveAt
(
vint
index
) {
if
(
0
<=
index
&&
index
<
items
.
Count
() &&
QueryRemove
(
index
,
items
[
index
])) {
BeforeRemove
(
index
,
items
[
index
]);
T
item
=
items
[
index
];
items
.
RemoveAt
(
index
);
AfterRemove
(
index
,
1
);
NotifyUpdateInternal
(
index
,
1
,
0
);
return
true
; }
return
false
; }
bool
RemoveRange
(
vint
index
,
vint
count
) {
if
(
count
<=
0
)
return
false
;
if
(
0
<=
index
&&
index
<
items
.
Count
() &&
index
+
count
<=
items
.
Count
()) {
for
(
vint
i
=
0
;
i
<
count
;
i
++) {
if
(!
QueryRemove
(
index
+
1
,
items
[
index
+
i
]))
return
false
; }
for
(
vint
i
=
0
;
i
<
count
;
i
++) {
BeforeRemove
(
index
+
i
,
items
[
index
+
i
]); }
items
.
RemoveRange
(
index
,
count
);
AfterRemove
(
index
,
count
);
NotifyUpdateInternal
(
index
,
count
,
0
);
return
true
; }
return
false
; }
bool
Clear
() {
vint
count
=
items
.
Count
();
for
(
vint
i
=
0
;
i
<
count
;
i
++) {
if
(!
QueryRemove
(
i
,
items
[
i
]))
return
false
; }
for
(
vint
i
=
0
;
i
<
count
;
i
++) {
BeforeRemove
(
i
,
items
[
i
]); }
items
.
Clear
();
AfterRemove
(
0
,
count
);
NotifyUpdateInternal
(
0
,
count
,
0
);
return
true
; }
vint
Insert
(
vint
index
,
const
T
&
item
) {
if
(
0
<=
index
&&
index
<=
items
.
Count
() &&
QueryInsert
(
index
,
item
)) {
BeforeInsert
(
index
,
item
);
items
.
Insert
(
index
,
item
);
AfterInsert
(
index
,
item
);
NotifyUpdateInternal
(
index
,
0
,
1
);
return
index
; }
else
{
return
-
1
; } }
bool
Set
(
vint
index
,
const
T
&
item
) {
if
(
0
<=
index
&&
index
<
items
.
Count
()) {
if
(
QueryRemove
(
index
,
items
[
index
]) &&
QueryInsert
(
index
,
item
)) {
BeforeRemove
(
index
,
items
[
index
]);
items
.
RemoveAt
(
index
);
AfterRemove
(
index
,
1
);
BeforeInsert
(
index
,
item
);
items
.
Insert
(
index
,
item
);
AfterInsert
(
index
,
item
);
NotifyUpdateInternal
(
index
,
1
,
1
);
return
true
; } }
return
false
; } };
/// <summary>An observable container that maintain an implementation of <see cref="reflection::description::IValueObservableList"/>.</summary>
/// <typeparam name="T">Type of elements.</typeparam>
/// <typeparam name="K">Type of the key type of elements. It is recommended to use the default value.</typeparam>
template
<
typename
T
>
class
ObservableList
:
public
ObservableListBase
<
T
> {
protected
:
Ptr
<
reflection
::
description
::
IValueObservableList
>
observableList
;
void
NotifyUpdateInternal
(
vint
start
,
vint
count
,
vint
newCount
)
override
{
if
(
observableList
) {
observableList
-
>
ItemChanged
(
start
,
count
,
newCount
); } }
public
:
/// <summary>
/// Get the maintained observable list.
/// <see cref="reflection::description::IValueObservableList::ItemChanged"/> of the observable list
/// will be automatically triggered when any changing happens.
/// </summary>
/// <returns>The maintained observable list.</returns>
/// <remarks>
/// <p>
/// <see cref="reflection::description::BoxParameter`1"/>
/// cannot turn any predefined C++ object to an reflectable observable list
/// and keep it binding to the C++ object.
/// When an reflectable observable list is required, ObservableList is strongly recommended.
/// </p>
/// </remarks>
Ptr
<
reflection
::
description
::
IValueObservableList
>
GetWrapper
() {
if
(!
observableList
) {
observableList
=
new
reflection
::
description
::
ValueObservableListWrapper
<
ObservableList
<
T
>*>(
this
); }
return
observableList
; } };
namespace
randomaccess_internal
{
template
<
typename
T
>
struct
RandomAccessable
<
ObservableListBase
<
T
>> {
static
const
bool
CanRead
=
true
;
static
const
bool
CanResize
=
false
; };
template
<
typename
T
>
struct
RandomAccessable
<
ObservableList
<
T
>> {
static
const
bool
CanRead
=
true
;
static
const
bool
CanResize
=
false
; }; } } }
#endif