xref: /MusicPlayer2/MusicPlayer2/UserUi.h (revision 5cbed78ffa3e46c269c1477ee52b2f3c3c07ac76)
1 #pragma once
2 #include "CPlayerUIBase.h"
3 #include "UIElement.h"
4 #include "TinyXml2Helper.h"
5 
6 class CUserUi :
7     public CPlayerUIBase
8 {
9 public:
10     CUserUi(CWnd* pMainWnd, const std::wstring& xml_path);
11     CUserUi(CWnd* pMainWnd, UINT id);    //此构造函数不传递xml文件的路径,id为xml界面资源ID
12     ~CUserUi();
13 
14     void LoadFromContents(const std::string& xml_contents);
15     void SetIndex(int index);
16     bool IsIndexValid() const;
17 
18     //遍历所有界面元素
19     //visible_only为true时,遇到stackElement时,只遍历stackElement下面可见的子节点
20     void IterateAllElements(std::function<bool(UiElement::Element*)> func, bool visible_only = false);
21     void IterateAllElementsInAllUi(std::function<bool(UiElement::Element*)> func);    //遍历每一个界面中的所有元素(包含big、narrow、small三个界面)
22     void VolumeAdjusted();      //当音量调整时需要调用此函数
23     void ResetVolumeToPlayTime();   //定时器SHOW_VOLUME_TIMER_ID响应时需要调用此函数
24     void PlaylistLocateToCurrent();     //播放列表控件使正在播放的条目可见
25     void ListLocateToCurrent();         //ui中的所有列表使正在播放的条目可见
26     void InitSearchBox(CWnd* pWnd);
27 
28     //清除所有搜索框的搜索状态。其中模板参数T是搜索框关联的列表元素的类型
29     template<class T>
30     void ClearSearchResult();
31 
32     void SaveStatackElementIndex(CArchive& archive);
33     void LoadStatackElementIndex(CArchive& archive);
34 
35     //查找一个UiElement中指定类型的元素
36     template<class T>
37     T* FindElement();
38 
39     //遍历所有指定类型的元素
40     //visible_only为true时,遇到stackElement时,只遍历stackElement下面可见的子节点
41     template<class T>
42     void IterateAllElements(std::function<bool(T*)> func, bool visible_only = false);
43 
44     enum { SHOW_VOLUME_TIMER_ID = 1635 };
45 
46     // 通过 CPlayerUIBase 继承
47     virtual void _DrawInfo(CRect draw_rect, bool reset = false) override;
48     virtual wstring GetUIName() override;
49     virtual bool LButtonUp(CPoint point) override;
50     virtual bool LButtonDown(CPoint point) override;
51     virtual void MouseMove(CPoint point) override;
52     virtual void MouseLeave() override;
53     virtual void RButtonUp(CPoint point) override;
54     virtual void RButtonDown(CPoint point) override;
55     virtual bool MouseWheel(int delta, CPoint point) override;
56     virtual bool DoubleClick(CPoint point) override;
57     virtual void UiSizeChanged() override;
58     virtual bool SetCursor() override;
59 
60 protected:
61     int m_index{ INT_MAX };
62     std::wstring m_xml_path;
63     std::shared_ptr<UiElement::Element> m_root_default;
64     std::shared_ptr<UiElement::Element> m_root_ui_big;
65     std::shared_ptr<UiElement::Element> m_root_ui_narrow;
66     std::shared_ptr<UiElement::Element> m_root_ui_small;
67     std::wstring m_ui_name;
68     std::map<UiElement::Element*, std::vector<std::shared_ptr<UiElement::Element>>>  m_stack_elements;      //保存所有的stackElement。key是其所在的ui节点,value是该ui节点下所有stackElement
69     bool m_last_mouse_in_draw_area{};
70 
71 public:
72     virtual int GetUiIndex() override;
73 
74     //确保每个界面的序号唯一
75     static void UniqueUiIndex(std::vector<std::shared_ptr<CUserUi>>& ui_list);
76 
77 protected:
78     std::shared_ptr<UiElement::Element> GetCurrentTypeUi() const;
79 
80     static std::shared_ptr<CUserUi> FindUiByIndex(const std::vector<std::shared_ptr<CUserUi>>& ui_list, int ui_index, std::shared_ptr<CUserUi> except);
81     static int GetMaxUiIndex(const std::vector<std::shared_ptr<CUserUi>>& ui_list);
82     std::shared_ptr<UiElement::Element> BuildUiElementFromXmlNode(tinyxml2::XMLElement* xml_node);      //从一个xml节点创建UiElement::Element元素及其所有子元素的对象
83 
84     virtual const std::vector<std::shared_ptr<UiElement::Element>>& GetStackElements() const;
85 
86 protected:
87     virtual void SwitchStackElement() override;
88 };
89 
90 template<class T>
ClearSearchResult()91 inline void CUserUi::ClearSearchResult()
92 {
93     IterateAllElementsInAllUi([&](UiElement::Element* element) ->bool {
94         UiElement::SearchBox* search_box{ dynamic_cast<UiElement::SearchBox*>(element) };
95         if (search_box != nullptr)
96         {
97             T* list_emelent = dynamic_cast<T*>(search_box->GetListElement());
98             if (list_emelent != nullptr)
99             {
100                 search_box->Clear();
101             }
102         }
103         return false;
104     });
105 }
106 
107 template<class T>
FindElement()108 inline T* CUserUi::FindElement()
109 {
110     T* element_found{};
111     IterateAllElements([&](UiElement::Element* element) ->bool {
112         T* ele = dynamic_cast<T*>(element);
113         if (ele != nullptr)
114         {
115             element_found = ele;
116             return true;
117         }
118         return false;
119     });
120 
121     return element_found;
122 }
123 
124 template<class T>
IterateAllElements(std::function<bool (T *)> func,bool visible_only)125 inline void CUserUi::IterateAllElements(std::function<bool(T*)> func, bool visible_only)
126 {
127     IterateAllElements([&](UiElement::Element* element) ->bool {
128         T* ele = dynamic_cast<T*>(element);
129         if (ele != nullptr)
130         {
131             return func(ele);
132         }
133         return false;
134     }, visible_only);
135 }
136