#ifndef VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSRESOURCEMANAGER
#define VCZH_PRESENTATION_ELEMENTS_GUIGRAPHICSRESOURCEMANAGER
#include "GuiGraphicsElementInterfaces.h"
#include "GuiGraphicsDocumentInterfaces.h"
#include "../NativeWindow/GuiNativeWindow.h"
namespace
{
namespace
{
namespace
{
class
GuiGraphicsResourceManager
:
public
{
protected
:
collections
::
<
>
;
collections
::
<
<
IGuiGraphicsRendererFactory
>>
;
public
:
GuiGraphicsResourceManager
();
~
GuiGraphicsResourceManager
();
(
const
&
);
void
(
,
<
IGuiGraphicsRendererFactory
>
);
IGuiGraphicsRendererFactory
*
(
);
virtual
*
(
*
) =
0
;
virtual
void
(
*
) =
0
;
virtual
void
(
*
) =
0
;
virtual
IGuiGraphicsLayoutProvider
*
() =
0
;
};
extern
GuiGraphicsResourceManager
*
GetGuiGraphicsResourceManager
();
extern
void
SetGuiGraphicsResourceManager
(
GuiGraphicsResourceManager
*
);
template
<
typename
>
class
:
public
,
public
,
public
<
>
{
protected
:
<
>
;
compositions
::
*
=
nullptr
;
void
(
compositions
::
*
)
override
{
=
;
}
void
InvokeOnCompositionStateChanged
()
{
if
(
)
{
compositions
::
InvokeOnCompositionStateChanged
(
);
}
}
void
InvokeOnElementStateChanged
()
{
if
(
)
{
();
}
InvokeOnCompositionStateChanged
();
}
public
:
static
*
()
{
auto
=
GetGuiGraphicsResourceManager
()->
(
::GetElementType());
CHECK_ERROR(rendererFactory != nullptr, L"This element is not supported by the selected renderer.");
do
{
if
(!(
rendererFactory
!=
nullptr
))
throw
(
L"This element is not supported by the selected renderer."
);}
while
(
0
);
auto
=
new
;
element
->renderer =
rendererFactory
->
();
element
->renderer->Initialize(
element
);
return
element
;
}
()
{
if
(
)
{
();
}
}
*
()
override
{
return
.
();
}
compositions
::
*
()
override
{
return
;
}
};
#define DEFINE_GUI_GRAPHICS_ELEMENT(TELEMENT, ELEMENT_TYPE_NAME)\
friend class GuiElementBase<TELEMENT>;\
public:\
static vint GetElementType()\
{\
static vint elementType = -1;\
if (elementType == -1)\
{\
auto manager = GetGuiGraphicsResourceManager();\
CHECK_ERROR(manager != nullptr, L"SetGuiGraphicsResourceManager must be called before registering element types.");\
elementType = manager->RegisterElementType(WString(ELEMENT_TYPE_NAME, false));\
}\
return elementType;\
}\
#define DEFINE_GUI_GRAPHICS_RENDERER(TELEMENT, TRENDERER, TTARGET)\
public:\
class Factory : public Object, public IGuiGraphicsRendererFactory\
{\
public:\
IGuiGraphicsRenderer* Create()\
{\
TRENDERER* renderer=new TRENDERER;\
renderer->factory=this;\
renderer->element=0;\
renderer->renderTarget=0;\
return renderer;\
}\
};\
protected:\
IGuiGraphicsRendererFactory* factory;\
TELEMENT* element;\
TTARGET* renderTarget;\
Size minSize;\
public:\
static void Register()\
{\
auto manager = GetGuiGraphicsResourceManager();\
CHECK_ERROR(manager != nullptr, L"SetGuiGraphicsResourceManager must be called before registering element renderers.");\
manager->RegisterRendererFactory(TELEMENT::GetElementType(), new TRENDERER::Factory);\
}\
IGuiGraphicsRendererFactory* GetFactory()override\
{\
return factory;\
}\
void Initialize(IGuiGraphicsElement* _element)override\
{\
element=dynamic_cast<TELEMENT*>(_element);\
InitializeInternal();\
}\
void Finalize()override\
{\
FinalizeInternal();\
}\
void SetRenderTarget(IGuiGraphicsRenderTarget* _renderTarget)override\
{\
TTARGET* oldRenderTarget=renderTarget;\
renderTarget=dynamic_cast<TTARGET*>(_renderTarget);\
RenderTargetChangedInternal(oldRenderTarget, renderTarget);\
}\
Size GetMinSize()override\
{\
return minSize;\
}\
#define DEFINE_CACHED_RESOURCE_ALLOCATOR(TKEY, TVALUE)\
public:\
static const vint DeadPackageMax=32;\
struct Package\
{\
TVALUE resource;\
vint counter;\
bool operator==(const Package& package)const{return false;}\
bool operator!=(const Package& package)const{return true;}\
};\
struct DeadPackage\
{\
TKEY key;\
TVALUE value;\
bool operator==(const DeadPackage& package)const{return false;}\
bool operator!=(const DeadPackage& package)const{return true;}\
};\
Dictionary<TKEY, Package> aliveResources;\
List<DeadPackage> deadResources;\
public:\
TVALUE Create(const TKEY& key)\
{\
vint index=aliveResources.Keys().IndexOf(key);\
if(index!=-1)\
{\
Package package=aliveResources.Values().Get(index);\
package.counter++;\
aliveResources.Set(key, package);\
return package.resource;\
}\
TVALUE resource;\
for(vint i=0;i<deadResources.Count();i++)\
{\
if(deadResources[i].key==key)\
{\
DeadPackage deadPackage=deadResources[i];\
deadResources.RemoveAt(i);\
resource=deadPackage.value;\
break;\
}\
}\
if(!resource)\
{\
resource=CreateInternal(key);\
}\
Package package;\
package.resource=resource;\
package.counter=1;\
aliveResources.Add(key, package);\
return package.resource;\
}\
void Destroy(const TKEY& key)\
{\
vint index=aliveResources.Keys().IndexOf(key);\
if(index!=-1)\
{\
Package package=aliveResources.Values().Get(index);\
package.counter--;\
if(package.counter==0)\
{\
aliveResources.Remove(key);\
if(deadResources.Count()==DeadPackageMax)\
{\
deadResources.RemoveAt(DeadPackageMax-1);\
}\
DeadPackage deadPackage;\
deadPackage.key=key;\
deadPackage.value=package.resource;\
deadResources.Insert(0, deadPackage);\
}\
else\
{\
aliveResources.Set(key, package);\
}\
}\
}
}
}
}
#endif