#include "pch.h" ////////////////////////////////////////////////////////////////////////////// // // NavPane // ////////////////////////////////////////////////////////////////////////////// class NavPaneImpl : public NavPane { private: ////////////////////////////////////////////////////////////////////////////// // // Types // ////////////////////////////////////////////////////////////////////////////// class Topic : public Pane { public: TRef m_ptopicParent; TRef m_ppane; TRef m_pstring; TRef m_pcolor; ZString m_str; ZString m_strMain; ZString m_strSecondary; int m_indent; Color m_color; Color m_colorHighlight; bool m_bInside; TRef m_peventSource; Topic( StringEventSourceImpl* peventSource, Topic* ptopicParent, IEngineFont* pfont, int indent, int width, const ZString& str, const ZString& strMain, const ZString& strSecondary, const Color& colorHighlight ) : m_peventSource(peventSource), m_ptopicParent(ptopicParent), m_str(str), m_strMain(strMain), m_strSecondary(strSecondary), m_indent(indent * 8), m_colorHighlight(colorHighlight), m_bInside(false) { m_ppane = new AnimatedImagePane( CreateStringImage( JustifyLeft(), pfont, m_pcolor = new ModifiableColorValue(Color::White()), width - m_indent, m_pstring = new ModifiableString(str), 4 ) ); InternalSetOffset(m_ppane, WinPoint(m_indent, 0)); InsertAtBottom(m_ppane); } void SetColor(const Color& color) { m_color = color; if (!m_bInside) { m_pcolor->SetValue(color); } } Pane* GetPane() { return this; } ////////////////////////////////////////////////////////////////////////////// // // Pane methods // ////////////////////////////////////////////////////////////////////////////// void UpdateLayout() { Child()->UpdateLayout(); InternalSetSize(WinPoint( Child()->XSize() + m_indent, Child()->YSize() )); } ////////////////////////////////////////////////////////////////////////////// // // IMouseInput methods // ////////////////////////////////////////////////////////////////////////////// void MouseEnter(IInputProvider* pprovider, const Point& point) { m_bInside = true; m_pcolor->SetValue(m_colorHighlight); } void MouseLeave(IInputProvider* pprovider) { m_bInside = false; m_pcolor->SetValue(m_color); } MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown) { if (button == 0 && bDown) { m_peventSource->Trigger(m_strMain); } return MouseResult(); } }; typedef TList > TopicList; ////////////////////////////////////////////////////////////////////////////// // // Members // ////////////////////////////////////////////////////////////////////////////// TopicList m_listTopic; TRef m_peventSource; TRef m_pfont; TRef m_pcolumn; TRef m_ptopicSelected; Color m_color; Color m_colorSelected; Color m_colorHighlight; public: ////////////////////////////////////////////////////////////////////////////// // // Constructor // ////////////////////////////////////////////////////////////////////////////// NavPaneImpl( IObjectList* plist, const Point& size, const Color& color, const Color& colorSelected, const Color& colorHighlight, IEngineFont* pfont ) : m_color(color), m_colorSelected(colorSelected), m_colorHighlight(colorHighlight), m_pfont(pfont) { m_peventSource = new StringEventSourceImpl(); InternalSetSize(WinPoint::Cast(size)); m_pcolumn = new ColumnPane(); InsertAtBottom(m_pcolumn); ReadTopicList(plist, 0, NULL); m_ptopicSelected = m_listTopic.GetFront(); UpdatePanes(); } ////////////////////////////////////////////////////////////////////////////// // // Implementation methods // ////////////////////////////////////////////////////////////////////////////// void ReadTopicList(IObjectList* plist, int indent, Topic* ptopicParent) { plist->GetFirst(); while (plist->GetCurrent() != NULL) { TRef ppair; CastTo(ppair, plist->GetCurrent()); TRef pstring; CastTo(pstring, ppair->GetNth(0)); TRef pstringMain; CastTo(pstringMain, ppair->GetNth(1)); TRef pstringSecondary; CastTo(pstringSecondary, ppair->GetNth(2)); TRef plistSubTopic; CastTo(plistSubTopic, ppair->GetLastNth(3)); TRef ptopic = new Topic( m_peventSource, ptopicParent, m_pfont, indent, XSize(), pstring->GetValue(), pstringMain->GetValue(), pstringSecondary->GetValue(), m_colorHighlight ); m_listTopic.PushEnd(ptopic); if (plistSubTopic->GetCount() != 0) { ReadTopicList(plistSubTopic, indent + 1, ptopic); } plist->GetNext(); } } bool IsTopicSelected(Topic* ptopicParent) { TRef ptopic = m_ptopicSelected; while (ptopic != NULL) { if (ptopic == ptopicParent) { return true; } ptopic = ptopic->m_ptopicParent; } return false; } bool IsTopicOpen(Topic* ptopic) { Topic* ptopicParent = ptopic->m_ptopicParent; // // Top level topics are always open // if (ptopicParent == NULL) { return true; } // // If all of this topic parents are selected this topic is open // while (ptopicParent != NULL) { if (!IsTopicSelected(ptopicParent)) { return false; } ptopicParent = ptopicParent->m_ptopicParent; } return true; } void UpdatePanes() { m_pcolumn->RemoveAllChildren(); TopicList::Iterator iter(m_listTopic); while (!iter.End()) { Topic* ptopic = iter.Value(); if (IsTopicOpen(ptopic)) { ptopic->SetColor( IsTopicSelected(ptopic) ? m_colorSelected : m_color ); m_pcolumn->InsertAtBottom(ptopic->GetPane()); } iter.Next(); } } Topic* FindTopic(const ZString& str) { TopicList::Iterator iter(m_listTopic); while (!iter.End()) { Topic* ptopic = iter.Value(); if (ptopic->m_strMain == str) { return ptopic; } iter.Next(); } return NULL; } ////////////////////////////////////////////////////////////////////////////// // // NavPane methods // ////////////////////////////////////////////////////////////////////////////// void SetTopic(const ZString& str) { m_ptopicSelected = FindTopic(str); UpdatePanes(); } const ZString& GetSecondary(const ZString& str) { Topic* ptopic = FindTopic(str); if (ptopic) { return ptopic->m_strSecondary; } else { return str; } } virtual TRef GetEventSource() { return m_peventSource; } ////////////////////////////////////////////////////////////////////////////// // // Pane methods // ////////////////////////////////////////////////////////////////////////////// void UpdateLayout() { m_pcolumn->UpdateLayout(); } }; ////////////////////////////////////////////////////////////////////////////// // // Factories // ////////////////////////////////////////////////////////////////////////////// class NavPaneFactory : public IFunction { public: TRef Apply(ObjectStack& stack) { TRef plist; CastTo(plist, (IObject*)stack.Pop()); TRef psize; CastTo(psize, (IObject*)stack.Pop()); TRef pcolor; CastTo(pcolor, (IObject*)stack.Pop()); TRef pcolorSelected; CastTo(pcolorSelected, (IObject*)stack.Pop()); TRef pcolorHighlight; CastTo(pcolorHighlight, (IObject*)stack.Pop()); TRef pfont; CastTo(pfont, (IObject*)stack.Pop()); return new NavPaneImpl( plist, psize->GetValue(), pcolor->GetValue(), pcolorSelected->GetValue(), pcolorHighlight->GetValue(), pfont->GetValue() ); } }; void AddNavPaneFactory( INameSpace* pns ) { pns->AddMember("NavPane", new NavPaneFactory()); }