#include "pch.h" ////////////////////////////////////////////////////////////////////////////// // // ImageButtonFacePane // ////////////////////////////////////////////////////////////////////////////// class ImageButtonFacePane : public ButtonFacePane { private: TRef 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)); // // Make sure the bitmap is an integer multiple on m_countFaces // 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) { // // Figure out which face to draw // 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; } } // // Draw the face // BltFace(psurface, face); // // Overlay the focus bitmap on top of the button // if (m_bFocus && (m_dwFaces & ButtonFaceFocus)) { BltFace(psurface, ButtonFaceFocus); } } }; TRef CreateButtonFacePane(Surface* psurface, DWORD dwFaces, int xmin, int xmax) { return new ImageButtonFacePane(psurface, dwFaces, xmin, xmax); } ////////////////////////////////////////////////////////////////////////////// // // // ////////////////////////////////////////////////////////////////////////////// class PaneButtonFacePane : public ButtonFacePane { private: TRef m_ppaneUp; TRef 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 CreateButtonFacePane(Pane* ppaneUp, Pane* ppaneDown) { return new PaneButtonFacePane(ppaneUp, ppaneDown); } ////////////////////////////////////////////////////////////////////////////// // // ButtonUIPane // ////////////////////////////////////////////////////////////////////////////// class ButtonUIPane : public ButtonPane, public IEventSink { TRef m_pfacePane; TRef m_peventSource; TRef m_peventSourceDoubleClick; TRef m_peventMouseEnterSource; TRef m_peventMouseLeaveSource; TRef m_peventMouseEnterWhileEnabledSource; TRef m_pprovider; TRef 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); } } ////////////////////////////////////////////////////////////////////////////// // // ButtonPane Methods // ////////////////////////////////////////////////////////////////////////////// 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; } ////////////////////////////////////////////////////////////////////////////// // // Pane Methods // ////////////////////////////////////////////////////////////////////////////// void UpdateLayout() { DefaultUpdateLayout(); } ////////////////////////////////////////////////////////////////////////////// // // IMouseInput Methods // ////////////////////////////////////////////////////////////////////////////// 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); // we should not have a timer set before the button is pressed 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(); } ////////////////////////////////////////////////////////////////////////////// // // IEventSink Methods // ////////////////////////////////////////////////////////////////////////////// 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; } }; ////////////////////////////////////////////////////////////////////////////// // // ButtonPane Contructors // ////////////////////////////////////////////////////////////////////////////// TRef CreateButton( ButtonFacePane* ppane, bool bToggle, float repeatRate, float repeatDelay ) { return new ButtonUIPane(ppane, repeatRate, repeatDelay, bToggle); } TRef CreateButton( Pane* ppaneUp, Pane* ppaneDown, bool bToggle, float repeatRate, float repeatDelay ) { return CreateButton( CreateButtonFacePane(ppaneUp, ppaneDown), bToggle, repeatRate, repeatDelay ); } TRef CreateButton(int size) { return CreateButton( new EdgePane(new Pane(NULL, WinPoint(size, size)), true), new EdgePane(new Pane(NULL, WinPoint(size, size)), false) ); } ////////////////////////////////////////////////////////////////////////////// // // ButtonBar // ////////////////////////////////////////////////////////////////////////////// class ButtonBarPaneImpl : public ButtonBarPane, public IEventSink { private: TRef m_peventSource; TRef m_peventMouseEnterWhileEnabledSource; TRef m_peventSink; TMap, int> m_mapEventSources; TMap, int> m_mapMouseEnterWhileEnabledSources; TMap > m_mapButtonPanes; TRef 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, int>::Iterator iter(m_mapMouseEnterWhileEnabledSources); while (!iter.End()) { iter.Key()->RemoveSink(m_peventSink); iter.Next(); } } { TMap, 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 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, int>::Iterator iter(m_mapMouseEnterWhileEnabledSources); while (!iter.End()) { iter.Key()->RemoveSink(m_peventSink); iter.Next(); } m_mapMouseEnterWhileEnabledSources.SetEmpty(); } { TMap, 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 pEventSource = pPane->GetEventSource(); m_mapEventSources.Set(pEventSource, nCmd); pEventSource->AddSink(m_peventSink); TRef 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 pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); pButtonPane->SetHidden(bHidden); } void SetEnabled(int nCmd, bool bEnabled) { TRef pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); pButtonPane->SetEnabled(bEnabled); } void SetChecked(int nCmd, bool bChecked) { TRef pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); pButtonPane->SetChecked(bChecked); } void SetChecked2(int nCmd, bool bChecked) { TRef pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); pButtonPane->SetChecked2(bChecked); } bool GetEnabled(int nCmd) { TRef pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); return pButtonPane->GetEnabled(); } bool GetChecked(int nCmd) { TRef pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); return pButtonPane->GetChecked(); } bool GetChecked2(int nCmd) { TRef pButtonPane; ZVerify(m_mapButtonPanes.Find(nCmd, pButtonPane)); return pButtonPane->GetChecked2(); } void FlashButton(int nCmd) { // NYI } int GetSelection() { return m_nCmdSelected; } void SetSelection(int nCmd) { if (m_bActAsTabs) { TRef 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(); } }; ////////////////////////////////////////////////////////////////////////////// // // ButtonBar // ////////////////////////////////////////////////////////////////////////////// TRef CreateButtonBarPane(bool bActAsTabs, bool bUseColumn) { return new ButtonBarPaneImpl(bActAsTabs, bUseColumn); } TRef CreateButtonBarPane(Surface* psurface, DWORD dwFaces, TVector& vecColumns, bool bActAsTabs) { TRef pbuttonBar = new ButtonBarPaneImpl(bActAsTabs, false); // // Create all the buttons // 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; }