#include "pch.h"
void IPopup::SetContainer(IPopupContainer* pcontainer)
{
m_pcontainer = pcontainer;
}
void IPopup::SetOwner(IPopup* ppopupOwner)
{
m_ppopupOwner = ppopupOwner;
}
void IPopup::OnClose()
{
}
void IPopup::ClosePopup(IPopup* ppopup)
{
m_pcontainer->ClosePopup(ppopup);
}
TRef<Image> IPopup::GetImage(Engine* pengine)
{
return CreatePaneImage(pengine, SurfaceType3D(), true, GetPane());
}
Rect IPopup::GetRect()
{
TRef<Pane> ppane = GetPane();
ppane->UpdateLayout();
return Rect(Point(0, 0), Point::Cast(ppane->GetSize()));
}
class PanePopup : public IPopup {
private:
TRef<Pane> m_ppane;
public:
PanePopup(Pane* ppane) :
m_ppane(ppane)
{
}
Pane* GetPane()
{
return m_ppane;
}
};
TRef<IPopup> CreatePanePopup(Pane* ppane)
{
return new PanePopup(ppane);
}
class PopupContainerImpl :
public IPopupContainerPrivate,
public WrapImage
{
private:
class PickImage : public Image {
private:
PopupContainerImpl* m_pppic;
public:
PickImage(PopupContainerImpl* pppic) :
m_pppic(pppic)
{
}
MouseResult HitTest(IInputProvider* pprovider, const Point& point, bool bCaptured)
{
return m_pppic->HitTest();
}
MouseResult Button(
IInputProvider* pprovider,
const Point& point,
int button,
bool bCaptured,
bool bInside,
bool bDown
) {
if (bDown) {
m_pppic->Picked();
}
return MouseResult();
}
ZString GetFunctionName() { return "ImagePopupContainer"; }
};
class PopupData : public IObject {
public:
TRef<PopupData> m_pdataNext;
TRef<IPopup> m_ppopup;
TRef<Image> m_pimage;
TRef<Image> m_ppickImage;
bool m_bCloseAll;
};
TRef<PopupData> m_pdata;
TRef<Engine> m_pengine;
TRef<GroupImage> m_pgroup;
TRef<RectValue> m_prectValue;
bool m_bCascadeRight;
public:
PopupContainerImpl() :
WrapImage(Image::GetEmpty()),
m_bCascadeRight(true)
{
m_pgroup = new GroupImage();
SetImage(m_pgroup);
}
MouseResult HitTest()
{
return (m_pdata != NULL) ? MouseResultHit() : MouseResult();
}
void Picked()
{
while (m_pdata && m_pdata->m_bCloseAll) {
ClosePopup(m_pdata->m_ppopup);
}
EngineWindow::DoHitTest();
}
void Initialize(
Engine* pengine,
RectValue* prectValue
) {
m_pengine = pengine;
m_prectValue = prectValue;
}
void OpenPopup(IPopup* ppopup, const Point& point, bool bCloseAll, IPopup* ppopupOwner)
{
OpenPopup(ppopup, new PointValue(point), bCloseAll, ppopupOwner);
}
void OpenPopup(IPopup* ppopup, PointValue* ppoint, bool bCloseAll, IPopup* ppopupOwner)
{
TRef<PopupData> pdata = new PopupData();
pdata->m_ppopup = ppopup;
pdata->m_bCloseAll = bCloseAll;
pdata->m_pimage =
new TransformImage(
ppopup->GetImage(m_pengine),
new TranslateTransform2(
ppoint
)
);
pdata->m_pdataNext = m_pdata;
m_pdata = pdata;
if (ppopupOwner == NULL) {
pdata->m_ppickImage = new PickImage(this);
m_pgroup->AddImageToTop(pdata->m_ppickImage);
}
m_pgroup->AddImageToTop(pdata->m_pimage);
ppopup->SetContainer(this);
if (ppopupOwner != NULL) {
ppopup->SetOwner(ppopupOwner);
}
}
void OpenPopup(IPopup* ppopup, const Rect& rect, bool bCloseAll, bool bCascadeDown, IPopup* ppopupOwner)
{
Rect rectPopup = ppopup->GetRect();
Rect rectContainer = m_prectValue->GetValue();
Point point;
if (m_bCascadeRight) {
if (rect.XMax() + rectPopup.XSize() > rectContainer.XMax()) {
point.SetX(rect.XMin() - rectPopup.XSize());
} else {
point.SetX(rect.XMax());
}
} else {
if (rect.XMin() - rectPopup.XSize() < 0) {
point.SetX(rect.XMax());
} else {
point.SetX(rect.XMin() - rectPopup.XSize());
}
}
if (point.X() + rectPopup.XSize() > rectContainer.XMax()) {
point.SetX(rectContainer.XMax() - rectPopup.XSize());
}
if (point.X() < 0) {
point.SetX(0);
}
if (bCascadeDown) {
if (rect.YMax() - rectPopup.YSize() < 0) {
bCascadeDown = false;
}
} else {
if (rect.YMin() + rectPopup.YSize() > rectContainer.YMax()) {
bCascadeDown = true;
}
}
if (bCascadeDown) {
if (rect.YMax() - rectPopup.YSize() < 0) {
point.SetY(0);
} else {
point.SetY(rect.YMax() - rectPopup.YSize());
}
} else {
if (rect.YMin() + rectPopup.YSize() > rectContainer.YMax()) {
point.SetY(rectContainer.YMax() - rectPopup.YSize());
} else {
point.SetY(rect.YMin());
}
}
OpenPopup(ppopup, point, bCloseAll, ppopupOwner);
}
class CenterRectPoint : public PointValue {
private:
const Rect& GetContainerRect() { return RectValue::Cast(GetChild(0))->GetValue(); }
const Rect& GetRect() { return RectValue::Cast(GetChild(1))->GetValue(); }
public:
CenterRectPoint(RectValue* prectContainer, RectValue* prect) :
PointValue(prectContainer, prect)
{
}
void Evaluate()
{
GetValueInternal() = (GetContainerRect().Size() - GetRect().Size()) / 2;
}
};
void OpenPopup(IPopup* ppopup, bool bCloseAll, IPopup* ppopupOwner)
{
OpenPopup(
ppopup,
new CenterRectPoint(m_prectValue, new RectValue(ppopup->GetRect())),
bCloseAll,
ppopupOwner
);
}
void ClosePopup(IPopup* ppopup)
{
while (m_pdata) {
m_pgroup->RemoveImage(m_pdata->m_pimage);
m_pgroup->RemoveImage(m_pdata->m_ppickImage);
m_pdata->m_ppopup->OnClose();
if (m_pdata->m_ppopup == ppopup) {
m_pdata = m_pdata->m_pdataNext;
break;
}
m_pdata = m_pdata->m_pdataNext;
}
if (m_pdata == NULL) {
m_bCascadeRight = true;
}
EngineWindow::DoHitTest();
}
bool IsEmpty()
{
return (m_pdata == NULL);
}
Image* GetImage()
{
return this;
}
bool OnChar(IInputProvider* pprovider, const KeyState& ks)
{
if (m_pdata != NULL) {
m_pdata->m_ppopup->OnChar(pprovider, ks);
return true;
}
return false;
}
bool OnKey(IInputProvider* pprovider, const KeyState& ks, bool& fForceTranslate)
{
if (m_pdata != NULL) {
m_pdata->m_ppopup->OnKey(pprovider, ks, fForceTranslate);
return true;
}
return false;
}
};
TRef<IPopupContainerPrivate> CreatePopupContainer()
{
return new PopupContainerImpl();
}