#include "pch.h"
class ImageButtonFacePane : public ButtonFacePane {
private:
TRef<Surface> m_psurface;
DWORD m_dwFaces;
int m_countFaces;
int m_xmin;
int m_xmax;
int m_xsize;
int m_ysize;
bool m_bFocus;
bool m_bEnabled;
bool m_bChecked;
bool m_bChecked2;
bool m_bDown;
bool m_bInside;
public:
ImageButtonFacePane(Surface* psurface, DWORD dwFaces, int xmin, int xmax) :
m_psurface(psurface),
m_dwFaces(dwFaces),
m_bFocus(false),
m_bEnabled(true),
m_bChecked(false),
m_bChecked2(false),
m_bDown(false),
m_bInside(false),
m_xmin(xmin),
m_xmax(xmax)
{
m_countFaces = CountBits(m_dwFaces);
const WinPoint& size = m_psurface->GetSize();
if (m_xmax == 0) {
m_xmin = 0;
m_xmax = size.X();
}
m_ysize = size.Y() / m_countFaces;
InternalSetSize(WinPoint(m_xmax - m_xmin, m_ysize));
ZAssert(m_countFaces * m_ysize == size.Y());
}
void SetFocus(bool bFocus)
{
if (m_bFocus != bFocus) {
m_bFocus = bFocus;
NeedPaint();
}
}
void SetEnabled(bool bEnabled)
{
if (m_bEnabled != bEnabled) {
m_bEnabled = bEnabled;
NeedPaint();
}
}
void SetChecked(bool bChecked)
{
if (m_bChecked != bChecked) {
m_bChecked = bChecked;
NeedPaint();
}
}
void SetChecked2(bool bChecked)
{
if (m_bChecked2 != bChecked) {
m_bChecked2 = bChecked;
NeedPaint();
}
}
void SetInside(bool bInside)
{
if (m_bInside != bInside) {
m_bInside = bInside;
NeedPaint();
}
}
void SetDown(bool bDown)
{
if (m_bDown != bDown) {
m_bDown = bDown;
NeedPaint();
}
}
int GetFaceIndex(DWORD face)
{
int index = 0;
DWORD faces = m_dwFaces;
while ((face & 1) == 0) {
if (faces & 1) {
index++;
}
faces = faces >> 1;
face = face >> 1;
}
if ((faces & 1) == 0) {
return -1;
}
return index;
}
void BltFace(Surface* psurface, DWORD face)
{
int index = GetFaceIndex(face);
if (index != -1) {
psurface->BitBlt(
WinPoint(0, 0),
m_psurface,
WinRect(
m_xmin,
index * m_ysize,
m_xmax,
(index + 1) * m_ysize
)
);
}
}
DWORD ChooseFace(DWORD dw, DWORD dwFallBack)
{
if (m_dwFaces & dw) {
return dw;
} else {
return dwFallBack;
}
}
void Paint(Surface* psurface)
{
DWORD face = 0;
if (m_bEnabled) {
if (m_bDown) {
if (m_bChecked2) {
face = ChooseFace(ButtonFaceChecked2Down, ButtonFaceUp);
} else if (m_bChecked) {
face = ChooseFace(ButtonFaceCheckedDown, ButtonFaceUp);
} else {
face = ChooseFace(ButtonFaceDown, ButtonFaceUp);
}
} else if (m_bInside) {
if (m_bChecked2) {
face =
ChooseFace(
ButtonFaceChecked2Inside,
ChooseFace(
ButtonFaceInside,
ChooseFace(
ButtonFaceChecked2Up,
ButtonFaceUp
)
)
);
} else if (m_bChecked) {
face =
ChooseFace(
ButtonFaceCheckedInside,
ChooseFace(
ButtonFaceInside,
ChooseFace(
ButtonFaceCheckedUp,
ButtonFaceUp
)
)
);
} else {
face = ChooseFace(ButtonFaceInside, ButtonFaceUp);
}
} else {
if (m_bChecked2) {
face = ChooseFace(ButtonFaceChecked2Up, ButtonFaceDown);
} else if (m_bChecked) {
face = ChooseFace(ButtonFaceCheckedUp, ButtonFaceDown);
} else {
face = ButtonFaceUp;
}
}
} else {
if (m_bChecked2) {
face = ChooseFace(ButtonFaceChecked2Disabled, ButtonFaceDisabled);
} else if (m_bChecked) {
face = ChooseFace(ButtonFaceCheckedDisabled, ButtonFaceDisabled);
} else {
face = ButtonFaceDisabled;
}
}
BltFace(psurface, face);
if (m_bFocus && (m_dwFaces & ButtonFaceFocus)) {
BltFace(psurface, ButtonFaceFocus);
}
}
};
TRef<ButtonFacePane> CreateButtonFacePane(Surface* psurface, DWORD dwFaces, int xmin, int xmax)
{
return new ImageButtonFacePane(psurface, dwFaces, xmin, xmax);
}
class PaneButtonFacePane : public ButtonFacePane {
private:
TRef<Pane> m_ppaneUp;
TRef<Pane> m_ppaneDown;
bool m_bDown;
bool m_bChecked;
public:
PaneButtonFacePane(Pane* ppaneUp, Pane* ppaneDown) :
m_ppaneUp(ppaneUp),
m_ppaneDown(ppaneDown),
m_bDown(false),
m_bChecked(false)
{
InsertAtBottom(m_ppaneUp);
if (m_ppaneDown) {
InsertAtBottom(m_ppaneDown);
m_ppaneDown->SetHidden(true);
}
}
void SetDown(bool bDown)
{
if (bDown != m_bDown) {
m_bDown = bDown;
NeedLayout();
NeedPaint();
}
}
virtual void SetChecked(bool bChecked)
{
if (bChecked != m_bChecked) {
m_bChecked = bChecked;
NeedLayout();
NeedPaint();
}
}
void UpdateLayout()
{
bool bFaceDown;
if (m_bChecked) {
bFaceDown = !m_bDown;
} else {
bFaceDown = m_bDown;
}
if (bFaceDown && m_ppaneDown) {
InternalSetHidden(m_ppaneUp, true);
InternalSetHidden(m_ppaneDown, false);
InternalSetExpand(m_ppaneDown, GetExpand());
m_ppaneDown->UpdateLayout();
InternalSetOffset(m_ppaneDown, WinPoint(0, 0));
InternalSetSize(m_ppaneDown->GetSize());
} else {
InternalSetHidden(m_ppaneUp, false);
if (m_ppaneDown) {
InternalSetHidden(m_ppaneDown, true);
}
InternalSetExpand(m_ppaneUp, GetExpand());
m_ppaneUp->UpdateLayout();
InternalSetOffset(m_ppaneUp, WinPoint(0, 0));
InternalSetSize(m_ppaneUp->GetSize());
}
}
};
TRef<ButtonFacePane> CreateButtonFacePane(Pane* ppaneUp, Pane* ppaneDown)
{
return new PaneButtonFacePane(ppaneUp, ppaneDown);
}
class ButtonUIPane :
public ButtonPane,
public IEventSink
{
TRef<ButtonFacePane> m_pfacePane;
TRef<EventSourceImpl> m_peventSource;
TRef<EventSourceImpl> m_peventSourceDoubleClick;
TRef<EventSourceImpl> m_peventMouseEnterSource;
TRef<EventSourceImpl> m_peventMouseLeaveSource;
TRef<EventSourceImpl> m_peventMouseEnterWhileEnabledSource;
TRef<IInputProvider> m_pprovider;
TRef<IEventSink> m_peventSinkDelegate;
bool m_bToggle;
bool m_bFocus;
bool m_bEnabled;
bool m_bChecked;
bool m_bChecked2;
bool m_bDown;
bool m_bInside;
bool m_bFirstEvent;
bool m_bDownTrigger;
float m_repeatDelay;
float m_repeatRate;
public:
ButtonUIPane(
ButtonFacePane* ppane,
float repeatRate,
float repeatDelay,
bool bToggle
) :
m_pfacePane(ppane),
m_peventSource(new EventSourceImpl()),
m_peventSourceDoubleClick(new EventSourceImpl()),
m_peventMouseEnterSource(new EventSourceImpl()),
m_peventMouseLeaveSource(new EventSourceImpl()),
m_peventMouseEnterWhileEnabledSource(new EventSourceImpl()),
m_repeatDelay(repeatDelay),
m_repeatRate(repeatRate),
m_bToggle(bToggle),
m_bFocus(false),
m_bEnabled(true),
m_bChecked(false),
m_bChecked2(false),
m_bDown(false),
m_bInside(false),
m_bDownTrigger(false)
{
InsertAtBottom(m_pfacePane);
m_peventSinkDelegate = IEventSink::CreateDelegate(this);
}
~ButtonUIPane()
{
if (m_pprovider)
{
m_pprovider->GetTimer()->RemoveSink(m_peventSinkDelegate);
m_pprovider = NULL;
}
}
void SetDown(bool bDown)
{
if (m_bDown != bDown) {
m_bDown = bDown;
m_pfacePane->SetDown(m_bDown);
}
}
void SetInside(bool bInside)
{
if (m_bInside != bInside) {
m_bInside = bInside;
m_pfacePane->SetInside(m_bInside);
}
}
void SetFocus(bool bFocus)
{
if (m_bFocus != bFocus) {
m_bFocus = bFocus;
m_pfacePane->SetFocus(m_bFocus);
}
}
void SetDownTrigger(bool bDownTrigger)
{
m_bDownTrigger = bDownTrigger;
}
void SetEnabled(bool bEnabled)
{
if (m_bEnabled != bEnabled) {
m_bEnabled = bEnabled;
m_pfacePane->SetEnabled(m_bEnabled);
if (bEnabled && m_bInside)
m_peventMouseEnterWhileEnabledSource->Trigger();
}
}
void SetChecked(bool bChecked)
{
if (m_bChecked != bChecked) {
m_bChecked = bChecked;
m_pfacePane->SetChecked(m_bChecked);
}
}
void SetChecked2(bool bChecked)
{
if (m_bChecked2 != bChecked) {
m_bChecked2 = bChecked;
m_pfacePane->SetChecked2(m_bChecked2);
}
}
void SetRepeat(float repeatRate, float repeatDelay)
{
if (repeatRate == 0 && m_pprovider != NULL) {
m_pprovider->GetTimer()->RemoveSink(m_peventSinkDelegate);
m_pprovider = NULL;
}
m_repeatRate = repeatRate;
m_repeatDelay = repeatDelay;
}
bool GetChecked()
{
return m_bChecked;
}
bool GetChecked2()
{
return m_bChecked2;
}
bool GetEnabled()
{
return m_bEnabled;
}
IEventSource* GetEventSource()
{
return m_peventSource;
}
IEventSource* GetDoubleClickEventSource()
{
return m_peventSourceDoubleClick;
}
IEventSource* GetMouseEnterEventSource()
{
return m_peventMouseEnterSource;
}
IEventSource* GetMouseLeaveEventSource()
{
return m_peventMouseLeaveSource;
}
IEventSource* GetMouseEnterWhileEnabledEventSource()
{
return m_peventMouseEnterWhileEnabledSource;
}
void UpdateLayout()
{
DefaultUpdateLayout();
}
void RemoveCapture()
{
if (m_pprovider) {
m_pprovider->GetTimer()->RemoveSink(m_peventSinkDelegate);
m_pprovider = NULL;
}
}
void MouseEnter(IInputProvider* pprovider, const Point& point)
{
SetInside(true);
m_peventMouseEnterSource->Trigger();
if (m_bEnabled)
m_peventMouseEnterWhileEnabledSource->Trigger();
}
void MouseLeave(IInputProvider* pprovider)
{
SetInside(false);
m_peventMouseLeaveSource->Trigger();
}
void MouseMove(IInputProvider* pprovider, const Point& point, bool bCaptured, bool bInside)
{
SetInside(bInside);
if (bCaptured) {
SetDown(bInside);
}
}
MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
{
if (button == 0) {
if (bDown) {
if (m_pprovider != NULL) {
assert(false); m_pprovider->GetTimer()->RemoveSink(m_peventSinkDelegate);
}
if (pprovider->IsDoubleClick()) {
m_peventSourceDoubleClick->Trigger();
} else if (m_bDownTrigger) {
m_peventSource->Trigger();
} else {
SetDown(true);
if (m_repeatRate != 0 && m_bEnabled) {
m_peventSource->Trigger();
if (m_repeatDelay != 0) {
m_bFirstEvent = true;
m_pprovider = pprovider;
pprovider->GetTimer()->AddSink(m_peventSinkDelegate, m_repeatDelay);
} else {
m_bFirstEvent = false;
m_pprovider = pprovider;
pprovider->GetTimer()->AddSink(m_peventSinkDelegate, m_repeatRate);
}
}
return MouseResultCapture();
}
} else {
if (bCaptured) {
bool bWasDown = m_bDown;
SetDown(false);
if (m_repeatRate == 0) {
if (bWasDown && m_bEnabled) {
if (m_bToggle) {
SetChecked(!m_bChecked);
}
m_peventSource->Trigger();
}
} else {
ZAssert(m_pprovider == NULL || pprovider == m_pprovider);
if (m_pprovider) {
m_pprovider->GetTimer()->RemoveSink(m_peventSinkDelegate);
m_pprovider = NULL;
}
}
return MouseResultRelease();
}
}
}
return MouseResult();
}
bool OnEvent(IEventSource* pevent)
{
if (m_bDown) {
m_peventSource->Trigger();
}
if (m_bFirstEvent) {
m_bFirstEvent = false;
m_pprovider->GetTimer()->AddSink(m_peventSinkDelegate, m_repeatRate);
return false;
}
return true;
}
};
TRef<ButtonPane> CreateButton(
ButtonFacePane* ppane,
bool bToggle,
float repeatRate,
float repeatDelay
) {
return new ButtonUIPane(ppane, repeatRate, repeatDelay, bToggle);
}
TRef<ButtonPane> CreateButton(
Pane* ppaneUp,
Pane* ppaneDown,
bool bToggle,
float repeatRate,
float repeatDelay
) {
return
CreateButton(
CreateButtonFacePane(ppaneUp, ppaneDown),
bToggle,
repeatRate,
repeatDelay
);
}
TRef<ButtonPane> CreateButton(int size)
{
return
CreateButton(
new EdgePane(new Pane(NULL, WinPoint(size, size)), true),
new EdgePane(new Pane(NULL, WinPoint(size, size)), false)
);
}
class ButtonBarPaneImpl :
public ButtonBarPane,
public IEventSink
{
private:
TRef<IntegerEventSourceImpl> m_peventSource;
TRef<IntegerEventSourceImpl> m_peventMouseEnterWhileEnabledSource;
TRef<IEventSink> m_peventSink;
TMap<TRef<IEventSource>, int> m_mapEventSources;
TMap<TRef<IEventSource>, int> m_mapMouseEnterWhileEnabledSources;
TMap<int, TRef<ButtonPane> > m_mapButtonPanes;
TRef<Pane> m_pRowPane;
int m_nCmdSelected;
bool m_bActAsTabs;
public:
ButtonBarPaneImpl(bool bActAsTabs, bool bUseColumn) :
m_nCmdSelected(-1),
m_bActAsTabs(bActAsTabs)
{
m_peventSource = new IntegerEventSourceImpl();
m_peventMouseEnterWhileEnabledSource = new IntegerEventSourceImpl();
m_peventSink = IEventSink::CreateDelegate(this);
if (!bUseColumn)
m_pRowPane = new RowPane();
else
m_pRowPane = new ColumnPane();
InsertAtBottom(m_pRowPane);
}
~ButtonBarPaneImpl()
{
{
TMap<TRef<IEventSource>, int>::Iterator iter(m_mapMouseEnterWhileEnabledSources);
while (!iter.End()) {
iter.Key()->RemoveSink(m_peventSink);
iter.Next();
}
}
{
TMap<TRef<IEventSource>, int>::Iterator iter(m_mapEventSources);
while (!iter.End()) {
iter.Key()->RemoveSink(m_peventSink);
iter.Next();
}
}
}
bool OnEvent(IEventSource* pevent)
{
int nCmd;
if (m_mapMouseEnterWhileEnabledSources.Find(pevent, nCmd))
{
m_peventMouseEnterWhileEnabledSource->Trigger(nCmd);
}
else
{
ZVerify(m_mapEventSources.Find(pevent, nCmd));
if (m_bActAsTabs) {
TRef<ButtonPane> pButtonPane;
if (m_nCmdSelected != -1) {
ZVerify(m_mapButtonPanes.Find(m_nCmdSelected, pButtonPane));
pButtonPane->SetChecked(false);
}
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
pButtonPane->SetChecked(true);
m_nCmdSelected = nCmd;
}
m_peventSource->Trigger(nCmd);
}
return true;
}
IIntegerEventSource* GetEventSource()
{
return m_peventSource;
}
IIntegerEventSource* GetMouseEnterWhileEnabledEventSource()
{
return m_peventMouseEnterWhileEnabledSource;
}
void RemoveAll()
{
{
TMap<TRef<IEventSource>, int>::Iterator iter(m_mapMouseEnterWhileEnabledSources);
while (!iter.End()) {
iter.Key()->RemoveSink(m_peventSink);
iter.Next();
}
m_mapMouseEnterWhileEnabledSources.SetEmpty();
}
{
TMap<TRef<IEventSource>, int>::Iterator iter(m_mapEventSources);
while (!iter.End()) {
iter.Key()->RemoveSink(m_peventSink);
iter.Next();
}
m_mapEventSources.SetEmpty();
}
m_pRowPane->RemoveAllChildren();
}
void InsertButton(ButtonPane* pPane, int nCmd)
{
ZAssert(nCmd != -1);
TRef<IEventSource> pEventSource = pPane->GetEventSource();
m_mapEventSources.Set(pEventSource, nCmd);
pEventSource->AddSink(m_peventSink);
TRef<IEventSource> pEnterEventSource = pPane->GetMouseEnterWhileEnabledEventSource();
m_mapMouseEnterWhileEnabledSources.Set(pEnterEventSource, nCmd);
pEnterEventSource->AddSink(m_peventSink);
m_mapButtonPanes.Set(nCmd, pPane);
m_pRowPane->InsertAtBottom(pPane);
if (m_bActAsTabs && m_mapButtonPanes.Count() == 1) {
m_nCmdSelected = nCmd;
pPane->SetChecked(true);
pPane->SetChecked2(false);
}
}
void SetHidden(int nCmd, bool bHidden)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
pButtonPane->SetHidden(bHidden);
}
void SetEnabled(int nCmd, bool bEnabled)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
pButtonPane->SetEnabled(bEnabled);
}
void SetChecked(int nCmd, bool bChecked)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
pButtonPane->SetChecked(bChecked);
}
void SetChecked2(int nCmd, bool bChecked)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
pButtonPane->SetChecked2(bChecked);
}
bool GetEnabled(int nCmd)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
return pButtonPane->GetEnabled();
}
bool GetChecked(int nCmd)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
return pButtonPane->GetChecked();
}
bool GetChecked2(int nCmd)
{
TRef<ButtonPane> pButtonPane;
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
return pButtonPane->GetChecked2();
}
void FlashButton(int nCmd)
{
}
int GetSelection()
{
return m_nCmdSelected;
}
void SetSelection(int nCmd)
{
if (m_bActAsTabs) {
TRef<ButtonPane> pButtonPane;
if (m_nCmdSelected != -1) {
ZVerify(m_mapButtonPanes.Find(m_nCmdSelected, pButtonPane));
pButtonPane->SetChecked(false);
pButtonPane->SetChecked2(false);
}
if (nCmd != -1) {
ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane));
pButtonPane->SetChecked(true);
m_nCmdSelected = nCmd;
}
m_nCmdSelected = nCmd;
}
}
void UpdateLayout()
{
DefaultUpdateLayout();
}
};
TRef<ButtonBarPane> CreateButtonBarPane(bool bActAsTabs, bool bUseColumn)
{
return new ButtonBarPaneImpl(bActAsTabs, bUseColumn);
}
TRef<ButtonBarPane> CreateButtonBarPane(Surface* psurface, DWORD dwFaces, TVector<int>& vecColumns, bool bActAsTabs)
{
TRef<ButtonBarPane> pbuttonBar = new ButtonBarPaneImpl(bActAsTabs, false);
int count = vecColumns.GetCount();
int xprev = 0;
for (int index = 0; index < count; index++) {
int x = vecColumns[index];
pbuttonBar->InsertButton(
CreateButton(CreateButtonFacePane(psurface, dwFaces, xprev, x)),
index
);
xprev = x;
}
return pbuttonBar;
}