1 #include "stdafx.h"
2 #include "UIElement.h"
3 #include "MusicPlayer2.h"
4 #include "MusicPlayerDlg.h"
5 #include "SongInfoHelper.h"
6 #include "UiMediaLibItemMgr.h"
7 #include "UserUi.h"
8 #include "MusicPlayerCmdHelper.h"
9 #include "UIWindowCmdHelper.h"
10 #include "CRecentList.h"
11 #include <stack>
12 #include "UiSearchBox.h"
13
14 ///////////////////////////////////////////////////////////////////////////////
15 //查找一个关联的节点
16 //element:被查找的节点
17 //返回值:查找结果
18 template<class T>
FindRelatedElement(UiElement::Element * element)19 static T* FindRelatedElement(UiElement::Element* element)
20 {
21 UiElement::Element* parent = element->pParent;
22 T* rtn_element = nullptr;
23 while (parent != nullptr)
24 {
25 //依次查找所有父节点下面的指定类型节点
26 for (const auto& ele : parent->childLst)
27 {
28 T* _element = dynamic_cast<T*>(ele.get());
29 if (_element != nullptr)
30 {
31 rtn_element = _element;
32 return rtn_element;
33 }
34 }
35 parent = parent->pParent;
36 }
37
38 //如果没有找到,则查找整个界面第一个指定类型节点
39 if (rtn_element == nullptr)
40 {
41 UiElement::Element* root = element->RootElement();
42 if (root != nullptr)
43 {
44 root->IterateAllElements([&](UiElement::Element* ele)->bool {
45 T* _element = dynamic_cast<T*>(ele);
46 if (_element != nullptr)
47 {
48 rtn_element = _element;
49 return true;
50 }
51 return false;
52 });
53 if (rtn_element != nullptr)
54 return rtn_element;
55 }
56 }
57 return nullptr;
58 }
59
60 ///////////////////////////////////////////////////////////////////////////////
61 ///////////////////////////////////////////////////////////////////////////////
Value(bool _is_vertical,Element * _owner)62 UiElement::Element::Value::Value(bool _is_vertical, Element* _owner)
63 : is_vertical(_is_vertical), owner(_owner)
64 {
65 }
66
FromString(const std::string str)67 void UiElement::Element::Value::FromString(const std::string str)
68 {
69 size_t index = str.find('%');
70 if (index != std::wstring::npos) //如果包含百分号
71 {
72 is_percentage = true;
73 value = atoi(str.substr(0, index).c_str());
74 }
75 else
76 {
77 is_percentage = false;
78 value = atoi(str.c_str());
79 }
80 valid = true;
81 }
82
GetValue(CRect parent_rect) const83 int UiElement::Element::Value::GetValue(CRect parent_rect) const
84 {
85 if (is_percentage) //如果是百分比,根据父元素的大小计算
86 {
87 if (is_vertical)
88 return parent_rect.Height() * value / 100;
89 else
90 return parent_rect.Width() * value / 100;
91 }
92 else //不是百分比,进行根据当前DPI对数值放大
93 {
94 return owner->ui->DPI(value);
95 }
96 }
97
IsValid() const98 bool UiElement::Element::Value::IsValid() const
99 {
100 return valid;
101 }
102
Draw()103 void UiElement::Element::Draw()
104 {
105 for (const auto& item : childLst)
106 {
107 if (item != nullptr && item->IsEnable(GetRect()))
108 item->Draw();
109 }
110 }
111
IsEnable(CRect parent_rect) const112 bool UiElement::Element::IsEnable(CRect parent_rect) const
113 {
114 if (hide_width.IsValid() && hide_width.GetValue(parent_rect) > parent_rect.Width())
115 return false;
116 if (hide_height.IsValid() && hide_height.GetValue(parent_rect) > parent_rect.Height())
117 return false;
118 return true;
119 }
120
GetMaxWidth(CRect parent_rect) const121 int UiElement::Element::GetMaxWidth(CRect parent_rect) const
122 {
123 if (max_width.IsValid())
124 return max_width.GetValue(parent_rect);
125 return INT_MAX;
126 }
127
GetWidth(CRect parent_rect) const128 int UiElement::Element::GetWidth(CRect parent_rect) const
129 {
130 int w{ width.GetValue(parent_rect) };
131 w = min(GetMaxWidth(parent_rect), w);
132 if (min_width.IsValid())
133 w = max(min_width.GetValue(parent_rect), w);
134 return w;
135 }
136
GetHeight(CRect parent_rect) const137 int UiElement::Element::GetHeight(CRect parent_rect) const
138 {
139 int h{ height.GetValue(parent_rect) };
140 if (max_height.IsValid())
141 h = min(max_height.GetValue(parent_rect), h);
142 if (min_height.IsValid())
143 h = max(min_height.GetValue(parent_rect), h);
144 return h;
145 }
146
IsWidthValid() const147 bool UiElement::Element::IsWidthValid() const
148 {
149 return width.IsValid();
150 }
151
IsHeightValid() const152 bool UiElement::Element::IsHeightValid() const
153 {
154 return height.IsValid();
155 }
156
GetRect() const157 CRect UiElement::Element::GetRect() const
158 {
159 return rect;
160 }
161
SetRect(CRect _rect)162 void UiElement::Element::SetRect(CRect _rect)
163 {
164 rect = _rect;
165 }
166
ClearRect()167 void UiElement::Element::ClearRect()
168 {
169 rect = CRect();
170 }
171
RootElement()172 UiElement::Element* UiElement::Element::RootElement()
173 {
174 Element* ele{ this };
175 while (ele != nullptr && ele->pParent != nullptr)
176 {
177 ele = ele->pParent;
178 }
179 return ele;
180 }
181
ParentRect() const182 CRect UiElement::Element::ParentRect() const
183 {
184 if (pParent == nullptr)
185 {
186 return rect;
187 }
188 else
189 {
190 pParent->CalculateRect();
191 return pParent->GetRect();
192 }
193 }
194
CalculateRect()195 void UiElement::Element::CalculateRect()
196 {
197 if (pParent == nullptr) //根节点的矩形不需要计算
198 return;
199
200 //判断父元素是否为布局元素
201 Layout* layout = dynamic_cast<Layout*>(pParent);
202 if (layout != nullptr)
203 {
204 //如果父元素为布局元素,则由布局元素计算子元素的矩形区域
205 return;
206 }
207 //父元素不是布局元素
208 else
209 {
210 //父元素的矩形区域
211 const CRect rect_parent{ ParentRect() };
212 const CRect rect_root{ RootElement()->GetRect() };
213 rect = rect_parent;
214 if (x.IsValid())
215 rect.left = x.GetValue(rect_parent) + rect_root.left;
216 if (y.IsValid())
217 rect.top = y.GetValue(rect_parent) + rect_root.top;
218
219 if (margin_left.IsValid())
220 rect.left = rect_parent.left + margin_left.GetValue(rect_parent);
221 if (margin_top.IsValid())
222 rect.top = rect_parent.top + margin_top.GetValue(rect_parent);
223 if (margin_right.IsValid())
224 rect.right = rect_parent.right - margin_right.GetValue(rect_parent);
225 if (margin_bottom.IsValid())
226 rect.bottom = rect_parent.bottom - margin_bottom.GetValue(rect_parent);
227
228 if (IsWidthValid())
229 {
230 if (!x.IsValid() && !margin_left.IsValid() && margin_right.IsValid())
231 rect.left = rect.right - width.GetValue(rect_parent);
232 else
233 rect.right = rect.left + width.GetValue(rect_parent);
234 }
235 if (IsHeightValid())
236 {
237 if (!y.IsValid() && !margin_top.IsValid() && margin_bottom.IsValid())
238 rect.top = rect.bottom - height.GetValue(rect_parent);
239 else
240 rect.bottom = rect.top + height.GetValue(rect_parent);
241 }
242 }
243 }
244
245
IterateElements(UiElement::Element * parent_element,std::function<bool (UiElement::Element *)> func,bool visible_only)246 void UiElement::Element::IterateElements(UiElement::Element* parent_element, std::function<bool(UiElement::Element*)> func, bool visible_only)
247 {
248 if (parent_element != nullptr)
249 {
250 if (func(parent_element))
251 return;
252 for (const auto& ele : parent_element->childLst)
253 {
254 if (visible_only)
255 {
256 StackElement* stack_element = dynamic_cast<UiElement::StackElement*>(ele.get());
257 if (stack_element != nullptr)
258 {
259 func(stack_element);
260 int cur_index = stack_element->GetCurIndex();
261 if (cur_index >= 0 && cur_index < static_cast<int>(stack_element->childLst.size()))
262 {
263 IterateElements(stack_element->childLst[cur_index].get(), func, visible_only);
264 }
265 }
266 else
267 {
268 IterateElements(ele.get(), func, visible_only);
269 }
270 }
271 else
272 {
273 IterateElements(ele.get(), func, visible_only);
274 }
275 }
276 }
277 }
278
IterateAllElements(std::function<bool (UiElement::Element *)> func,bool visible_only)279 void UiElement::Element::IterateAllElements(std::function<bool(UiElement::Element*)> func, bool visible_only)
280 {
281 IterateElements(this, func, visible_only);
282 }
283
SetUi(CPlayerUIBase * _ui)284 void UiElement::Element::SetUi(CPlayerUIBase* _ui)
285 {
286 ui = _ui;
287 }
288
AddChild(std::shared_ptr<Element> child)289 void UiElement::Element::AddChild(std::shared_ptr<Element> child)
290 {
291 child->pParent = this;
292 childLst.push_back(child);
293 }
294
295
296 ///////////////////////////////////////////////////////////////////////////////
297 ///////////////////////////////////////////////////////////////////////////////
CalculateChildrenRect()298 void UiElement::Layout::CalculateChildrenRect()
299 {
300 //水平布局
301 if (type == Horizontal)
302 {
303 vector<int> size_list; // 已确定子元素尺寸记录(不含边距),未确定项为INT_MIN
304 int total_size{}; // 所有已指定元素的宽度(非浮动宽度)与已确定的总边距
305 int item_fixed_size_num{}; // 有固定宽度的元素的个数
306
307 // 第一次遍历,获取固定不变的尺寸数据
308 for (const auto& child : childLst)
309 {
310 if (!child->IsEnable(GetRect())) // 设置为不显示时按尺寸为0的固定尺寸元素处理,并忽略此元素边距
311 {
312 size_list.push_back(0);
313 item_fixed_size_num++;
314 }
315 else
316 {
317 if (child->IsWidthValid() && child->proportion < 1) // proportion设定时忽略width
318 {
319 int width{ child->GetWidth(GetRect()) };
320 total_size += width;
321 size_list.push_back(width);
322 item_fixed_size_num++;
323 }
324 else
325 {
326 size_list.push_back(INT_MIN); // 这个子元素尺寸未定
327 }
328 if (child->margin_left.IsValid())
329 total_size += child->margin_left.GetValue(GetRect());
330 if (child->margin_right.IsValid())
331 total_size += child->margin_right.GetValue(GetRect());
332 }
333 }
334
335 int left_space{}; // 全部具有固定尺寸时首子元素与开始边缘的间距
336 bool all_ok{};
337 while (!all_ok)
338 {
339 //如果每个元素都有固定的尺寸,则让这些元素在布局中居中
340 if (childLst.size() == item_fixed_size_num)
341 {
342 left_space = (GetRect().Width() - total_size) / 2;
343 if (left_space < 0) // 空间不足时优先显示容器前端元素
344 left_space = 0;
345 all_ok = true;
346 }
347 else
348 {
349 // 此时size_list中为INT_MIN的子元素应按比例处理
350 int proportion{}; // 各未固定子元素比例系数和
351 for (size_t i{}; i < childLst.size(); ++i) // 计算比例系数和
352 {
353 if (size_list[i] == INT_MIN)
354 proportion += max(childLst[i]->proportion, 1); // 均未设置时按1处理
355 }
356 // 逐个检查是否符合最值
357 bool ok{ true };
358 for (size_t i{}; i < childLst.size(); ++i)
359 {
360 if (size_list[i] == INT_MIN)
361 {
362 auto& child{ childLst[i] };
363 int size{ (GetRect().Width() - total_size) * max(child->proportion, 1) / proportion };
364 int max_size{ child->GetMaxWidth(GetRect()) };
365 int min_size{ child->min_width.IsValid() ? child->min_width.GetValue(GetRect()) : 0 };
366 if (size < min_size || max_size < min_size) // 比例与最值冲突时按最值处理并将此元素标记为固定尺寸元素,由于文本收缩的引入最大值可能比预期小故给与最小值更高的优先级
367 {
368 size_list[i] = min_size;
369 total_size += min_size;
370 item_fixed_size_num++;
371 ok = false;
372 break;
373 }
374 else if (size > max_size)
375 {
376 size_list[i] = max_size;
377 total_size += max_size;
378 item_fixed_size_num++;
379 ok = false;
380 break;
381 }
382 }
383 }
384 if (!ok) // ok为false说明增加了一个固定元素,重新计算比例
385 {
386 continue;
387 }
388 else // ok为true说明当前比例可满足最值要求,下面正式进行比例应用
389 {
390 for (size_t i{}; i < childLst.size(); ++i)
391 {
392 if (size_list[i] == INT_MIN)
393 {
394 auto& child{ childLst[i] };
395 int size{ (GetRect().Width() - total_size) * max(child->proportion, 1) / proportion };
396 size_list[i] = max(size, 0);
397 }
398 }
399 left_space = 0;
400 all_ok = true;
401 }
402 }
403 }
404 ASSERT(find(size_list.begin(), size_list.end(), INT_MIN) == size_list.end());
405
406 //计算每个子元素的矩形区域
407 int w{};
408 bool first_child{ true };
409 for (size_t i{}; i < childLst.size(); i++)
410 {
411 auto& child{ childLst[i] };
412 CRect child_rect{};
413 if (child->IsHeightValid())
414 {
415 int child_height = child->GetHeight(GetRect());
416 int max_height = GetRect().Height() - child->margin_top.GetValue(GetRect()) - child->margin_bottom.GetValue(GetRect());
417 if (child_height > max_height)
418 child_height = max_height;
419 child_rect.top = GetRect().top + (GetRect().Height() - child_height) / 2;
420 child_rect.bottom = child_rect.top + child->GetHeight(GetRect());
421 }
422 else
423 {
424 child_rect.top = GetRect().top + child->margin_top.GetValue(GetRect());
425 child_rect.bottom = GetRect().bottom - child->margin_bottom.GetValue(GetRect());
426 }
427 if (child->IsEnable(GetRect()))
428 {
429 if (first_child)
430 {
431 child_rect.left = GetRect().left + child->margin_left.GetValue(GetRect()) + left_space;
432 first_child = false;
433 }
434 else
435 {
436 child_rect.left = w + child->margin_left.GetValue(GetRect());
437 }
438 child_rect.right = child_rect.left + size_list[i];
439 w = child_rect.right + child->margin_right.GetValue(GetRect());
440 }
441 else
442 {
443 child_rect.left = w;
444 child_rect.right = w;
445 }
446 child->SetRect(child_rect);
447 }
448 }
449 //垂直布局
450 else
451 {
452 vector<int> size_list; // 已确定子元素尺寸记录(不含边距),未确定项为INT_MIN
453 int total_size{}; // 所有已指定元素的高度(非浮动高度)与已确定的总边距
454 int item_fixed_size_num{}; // 有固定高度的元素的个数
455
456 // 第一次遍历,获取固定不变的尺寸数据
457 for (const auto& child : childLst)
458 {
459 if (!child->IsEnable(GetRect())) // 设置为不显示时按尺寸为0的固定尺寸元素处理
460 {
461 size_list.push_back(0);
462 item_fixed_size_num++;
463 }
464 else
465 {
466 if (child->IsHeightValid() && child->proportion < 1) // proportion设定时忽略height
467 {
468 int height{ child->GetHeight(GetRect()) };
469 total_size += height;
470 size_list.push_back(height);
471 item_fixed_size_num++;
472 }
473 else
474 {
475 size_list.push_back(INT_MIN); // 这个子元素尺寸未定
476 }
477 if (child->margin_top.IsValid())
478 total_size += child->margin_top.GetValue(GetRect());
479 if (child->margin_bottom.IsValid())
480 total_size += child->margin_bottom.GetValue(GetRect());
481 }
482 }
483
484 int top_space{}; // 全部具有固定尺寸时首子元素与开始边缘的间距
485 bool all_ok{};
486 while (!all_ok)
487 {
488 //如果每个元素都有固定的尺寸,则让这些元素在布局中居中
489 if (childLst.size() == item_fixed_size_num)
490 {
491 top_space = (GetRect().Height() - total_size) / 2;
492 if (top_space < 0) // 空间不足时优先显示容器前端元素
493 top_space = 0;
494 all_ok = true;
495 }
496 else
497 {
498 // 此时size_list中为INT_MIN的子元素应按比例处理
499 int proportion{}; // 各未固定子元素比例系数和
500 for (size_t i{}; i < childLst.size(); ++i) // 计算比例系数和
501 {
502 if (size_list[i] == INT_MIN)
503 proportion += max(childLst[i]->proportion, 1); // 均未设置时按1处理
504 }
505 // 逐个检查是否符合最值
506 bool ok{ true };
507 for (size_t i{}; i < childLst.size(); ++i)
508 {
509 if (size_list[i] == INT_MIN)
510 {
511 auto& child{ childLst[i] };
512 int size{ (GetRect().Height() - total_size) * max(child->proportion, 1) / proportion };
513 int max_size{ child->max_height.IsValid() ? child->max_height.GetValue(GetRect()) : INT_MAX };
514 int min_size{ child->min_height.IsValid() ? child->min_height.GetValue(GetRect()) : 0 };
515 if (size < min_size || max_size < min_size) // 比例与最值冲突时按最值处理并将此元素标记为固定尺寸元素
516 {
517 size_list[i] = min_size;
518 total_size += min_size;
519 item_fixed_size_num++;
520 ok = false;
521 break;
522 }
523 else if (size > max_size)
524 {
525 size_list[i] = max_size;
526 total_size += max_size;
527 item_fixed_size_num++;
528 ok = false;
529 break;
530 }
531 }
532 }
533 if (!ok) // ok为false说明增加了一个固定元素,重新计算比例
534 {
535 continue;
536 }
537 else // ok为true说明当前比例可满足最值要求,下面正式进行比例应用
538 {
539 for (size_t i{}; i < childLst.size(); ++i)
540 {
541 if (size_list[i] == INT_MIN)
542 {
543 auto& child{ childLst[i] };
544 int size{ (GetRect().Height() - total_size) * max(child->proportion, 1) / proportion };
545 size_list[i] = max(size, 0);
546 }
547 }
548 top_space = 0;
549 all_ok = true;
550 }
551 }
552 }
553 ASSERT(find(size_list.begin(), size_list.end(), INT_MIN) == size_list.end());
554
555 // 计算每个子元素的矩形区域
556 int h{};
557 bool first_child{ true };
558 for (size_t i{}; i < childLst.size(); i++)
559 {
560 auto& child{ childLst[i] };
561 CRect child_rect{};
562 if (child->IsWidthValid())
563 {
564 int child_width = child->GetWidth(GetRect());
565 int max_width = GetRect().Width() - child->margin_left.GetValue(GetRect()) - child->margin_right.GetValue(GetRect());
566 if (child_width > max_width)
567 child_width = max_width;
568 child_rect.left = GetRect().left + (GetRect().Width() - child_width) / 2;
569 child_rect.right = child_rect.left + child->GetWidth(GetRect());
570 }
571 else
572 {
573 child_rect.left = GetRect().left + child->margin_left.GetValue(GetRect());
574 child_rect.right = GetRect().right - child->margin_right.GetValue(GetRect());
575 }
576 if (child->IsEnable(GetRect()))
577 {
578 if (first_child)
579 {
580 child_rect.top = GetRect().top + child->margin_top.GetValue(GetRect()) + top_space;
581 first_child = false;
582 }
583 else
584 {
585 child_rect.top = h + child->margin_top.GetValue(GetRect());
586 }
587 child_rect.bottom = child_rect.top + size_list[i];
588 h = child_rect.bottom + child->margin_bottom.GetValue(GetRect());
589 }
590 else
591 {
592 child_rect.top = h;
593 child_rect.bottom = h;
594 }
595 child->SetRect(child_rect);
596 }
597 }
598 }
599
600
Draw()601 void UiElement::Layout::Draw()
602 {
603 CalculateRect();
604 CalculateChildrenRect();
605 Element::Draw();
606 }
607
608
SetCurrentElement(int index)609 void UiElement::StackElement::SetCurrentElement(int index)
610 {
611 if (index >= 0 && index < static_cast<int>(childLst.size()))
612 cur_index = index;
613 else
614 index = 0;
615 }
616
SwitchDisplay(bool previous)617 void UiElement::StackElement::SwitchDisplay(bool previous)
618 {
619 if (previous)
620 {
621 cur_index--;
622 if (cur_index < 0)
623 cur_index = static_cast<int>(childLst.size()) - 1;
624 }
625 else
626 {
627 cur_index++;
628 if (cur_index >= static_cast<int>(childLst.size()))
629 cur_index = 0;
630 }
631 }
632
Draw()633 void UiElement::StackElement::Draw()
634 {
635 auto cur_element{ CurrentElement() };
636
637 //清空不显示的子元素的矩形区域
638 for (size_t i{}; i < childLst.size(); i++)
639 {
640 if (cur_element != childLst[i])
641 {
642 childLst[i]->IterateAllElements([&](UiElement::Element* element) ->bool {
643 if (element != nullptr)
644 element->ClearRect();
645 return false;
646 });
647 }
648 }
649
650 if (cur_element != nullptr)
651 cur_element->Draw();
652 //只绘制一个子元素
653 //不调用基类的Draw方法。
654
655 //绘制指示器
656 if (show_indicator)
657 {
658 //计算指示器的位置
659 int indicator_width = ui->DPI(12) * childLst.size();
660 indicator.rect.top = GetRect().bottom + ui->DPI(2) + ui->DPI(indicator_offset);
661 indicator.rect.bottom = indicator.rect.top + ui->DPI(12);
662 indicator.rect.left = GetRect().left + (GetRect().Width() - indicator_width) / 2;
663 indicator.rect.right = indicator.rect.left + indicator_width;
664 indicator.rect.InflateRect(ui->DPI(2), ui->DPI(2));
665 //绘制指示器
666 ui->DrawStackIndicator(indicator, childLst.size(), cur_index);
667 }
668 }
669
GetCurIndex() const670 int UiElement::StackElement::GetCurIndex() const
671 {
672 return cur_index;
673 }
674
CurrentElement()675 std::shared_ptr<UiElement::Element> UiElement::StackElement::CurrentElement()
676 {
677 if (hover_to_switch && mouse_hover)
678 {
679 int next_index = cur_index + 1;
680 if (next_index < 0 || next_index >= static_cast<int>(childLst.size()))
681 next_index = 0;
682 return GetElement(next_index);
683 }
684 else
685 {
686 return GetElement(cur_index);
687 }
688 }
689
GetElement(int index)690 std::shared_ptr<UiElement::Element> UiElement::StackElement::GetElement(int index)
691 {
692 if (childLst.empty())
693 return nullptr;
694 else if (index >= 0 && index < static_cast<int>(childLst.size()))
695 return childLst[index];
696 else
697 return childLst[0];
698 }
699
700
Draw()701 void UiElement::Rectangle::Draw()
702 {
703 CalculateRect();
704 ui->DrawRectangle(rect, no_corner_radius, theme_color, color_mode);
705 Element::Draw();
706 }
707
Draw()708 void UiElement::Button::Draw()
709 {
710 CalculateRect();
711 switch (key)
712 {
713 case CPlayerUIBase::BTN_TRANSLATE:
714 ui->DrawTranslateButton(rect);
715 break;
716 case CPlayerUIBase::BTN_LRYIC:
717 ui->DrawDesktopLyricButton(rect);
718 break;
719 case CPlayerUIBase::BTN_AB_REPEAT:
720 ui->DrawABRepeatButton(rect);
721 break;
722 case CPlayerUIBase::BTN_KARAOKE:
723 ui->DrawKaraokeButton(rect);
724 break;
725 default:
726 ui->DrawUIButton(rect, key, big_icon, show_text, font_size);
727 break;
728 }
729 Element::Draw();
730 }
731
FromString(const std::string & key_type)732 void UiElement::Button::FromString(const std::string& key_type)
733 {
734 if (key_type == "menu")
735 key = CPlayerUIBase::BTN_MENU;
736 else if (key_type == "miniMode")
737 key = CPlayerUIBase::BTN_MINI;
738 else if (key_type == "miniModeClose")
739 key = CPlayerUIBase::BTN_CLOSE;
740 else if (key_type == "fullScreen")
741 key = CPlayerUIBase::BTN_FULL_SCREEN;
742 else if (key_type == "repeatMode")
743 key = CPlayerUIBase::BTN_REPETEMODE;
744 else if (key_type == "settings")
745 key = CPlayerUIBase::BTN_SETTING;
746 else if (key_type == "equalizer")
747 key = CPlayerUIBase::BTN_EQ;
748 else if (key_type == "skin")
749 key = CPlayerUIBase::BTN_SKIN;
750 else if (key_type == "info")
751 key = CPlayerUIBase::BTN_INFO;
752 else if (key_type == "find")
753 key = CPlayerUIBase::BTN_FIND;
754 else if (key_type == "abRepeat")
755 key = CPlayerUIBase::BTN_AB_REPEAT;
756 else if (key_type == "desktopLyric")
757 key = CPlayerUIBase::BTN_LRYIC;
758 else if (key_type == "lyricTranslate")
759 key = CPlayerUIBase::BTN_TRANSLATE;
760 else if (key_type == "stop")
761 key = CPlayerUIBase::BTN_STOP;
762 else if (key_type == "previous")
763 key = CPlayerUIBase::BTN_PREVIOUS;
764 else if (key_type == "next")
765 key = CPlayerUIBase::BTN_NEXT;
766 else if (key_type == "playPause")
767 key = CPlayerUIBase::BTN_PLAY_PAUSE;
768 else if (key_type == "favorite")
769 key = CPlayerUIBase::BTN_FAVOURITE;
770 else if (key_type == "mediaLib")
771 key = CPlayerUIBase::BTN_MEDIA_LIB;
772 else if (key_type == "showPlaylist")
773 key = CPlayerUIBase::BTN_SHOW_PLAYLIST;
774 else if (key_type == "addToPlaylist")
775 key = CPlayerUIBase::BTN_ADD_TO_PLAYLIST;
776 else if (key_type == "switchDisplay")
777 key = CPlayerUIBase::BTN_SWITCH_DISPLAY;
778 else if (key_type == "darkLightMode")
779 key = CPlayerUIBase::BTN_DARK_LIGHT;
780 else if (key_type == "locateTrack")
781 key = CPlayerUIBase::BTN_LOCATE_TO_CURRENT;
782 else if (key_type == "openFolder")
783 key = CPlayerUIBase::BTN_OPEN_FOLDER;
784 else if (key_type == "newPlaylist")
785 key = CPlayerUIBase::BTN_NEW_PLAYLIST;
786 else if (key_type == "playMyFavourite")
787 key = CPlayerUIBase::BTN_PLAY_MY_FAVOURITE;
788 else if (key_type == "medialibFolderSort")
789 key = CPlayerUIBase::BTN_MEDIALIB_FOLDER_SORT;
790 else if (key_type == "medialibPlaylistSort")
791 key = CPlayerUIBase::BTN_MEDIALIB_PLAYLIST_SORT;
792 else if (key_type == "karaoke")
793 key = CPlayerUIBase::BTN_KARAOKE;
794 else
795 key = CPlayerUIBase::BTN_INVALID;
796 }
797
GetMaxWidth(CRect parent_rect) const798 int UiElement::Button::GetMaxWidth(CRect parent_rect) const
799 {
800 //显示文本,并且没有指定宽度时时跟随文本宽度
801 if (show_text && !IsWidthValid())
802 {
803 std::wstring text = ui->GetButtonText(key);
804 //第一次执行到这里时,由于rect还没有从layout元素中计算出来,因此这里做一下判断,如果高度为0,则直接获取height的值
805 int btn_height = rect.Height();
806 if (btn_height == 0)
807 btn_height = Element::height.GetValue(parent_rect);
808 int right_space = (btn_height - ui->DPI(16)) / 2;
809
810 //计算文本宽度前先设置一下字体
811 UiFontGuard set_font(ui, font_size);
812
813 int width_text{ ui->m_draw.GetTextExtent(text.c_str()).cx + right_space + btn_height };
814
815 int width_max{ max_width.IsValid() ? max_width.GetValue(parent_rect) : INT_MAX };
816 return min(width_text, width_max);
817 }
818 else
819 {
820 return Element::GetMaxWidth(parent_rect);
821 }
822 }
823
ClearRect()824 void UiElement::Button::ClearRect()
825 {
826 Element::ClearRect();
827 ui->m_buttons[key].rect = CRect();
828 }
829
Draw()830 void UiElement::Text::Draw()
831 {
832 CalculateRect();
833 std::wstring draw_text{ GetText() };
834
835 //设置字体
836 UiFontGuard set_font(ui, font_size);
837
838 COLORREF text_color{};
839 if (color_mode == CPlayerUIBase::RCM_LIGHT)
840 text_color = ColorTable::WHITE;
841 else if (color_mode == CPlayerUIBase::RCM_DARK)
842 text_color = theApp.m_app_setting_data.theme_color.dark2;
843 else
844 text_color = ui->m_colors.color_text;
845
846 int text_extent{ ui->m_draw.GetTextExtent(draw_text.c_str()).cx }; //文本的实际宽度
847 if (rect.Width() >= text_extent) //如果绘图区域的宽度大于文本的实际宽度,则文本不需要滚动显示
848 {
849 ui->m_draw.DrawWindowText(rect, draw_text.c_str(), text_color, align);
850 }
851 else
852 {
853 switch (style)
854 {
855 case UiElement::Text::Static:
856 ui->m_draw.DrawWindowText(rect, draw_text.c_str(), text_color, align);
857 break;
858 case UiElement::Text::Scroll:
859 ui->m_draw.DrawScrollText(rect, draw_text.c_str(), text_color, ui->GetScrollTextPixel(), false, scroll_info, false);
860 break;
861 case UiElement::Text::Scroll2:
862 ui->m_draw.DrawScrollText2(rect, draw_text.c_str(), text_color, ui->GetScrollTextPixel(), false, scroll_info, false);
863 break;
864 default:
865 break;
866 }
867 }
868
869 Element::Draw();
870 }
871
GetMaxWidth(CRect parent_rect) const872 int UiElement::Text::GetMaxWidth(CRect parent_rect) const
873 {
874 if (!width_follow_text)
875 return UiElement::Element::GetMaxWidth(parent_rect);
876 else
877 {
878 int width_text{ ui->m_draw.GetTextExtent(GetText().c_str()).cx + ui->DPI(4) };
879 int width_max{ max_width.IsValid() ? max_width.GetValue(parent_rect) : INT_MAX };
880 return min(width_text, width_max);
881 }
882 }
883
GetText() const884 std::wstring UiElement::Text::GetText() const
885 {
886 std::wstring draw_text{};
887 switch (type)
888 {
889 case UiElement::Text::UserDefine:
890 draw_text = text;
891 break;
892 case UiElement::Text::Title:
893 draw_text = CPlayer::GetInstance().GetCurrentSongInfo().GetTitle();
894 break;
895 case UiElement::Text::Artist:
896 draw_text = CPlayer::GetInstance().GetCurrentSongInfo().GetArtist();
897 break;
898 case UiElement::Text::Album:
899 draw_text = CPlayer::GetInstance().GetCurrentSongInfo().GetAlbum();
900 break;
901 case UiElement::Text::ArtistTitle:
902 draw_text = CPlayer::GetInstance().GetCurrentSongInfo().GetArtist() + L" - " + CPlayer::GetInstance().GetCurrentSongInfo().GetTitle();
903 break;
904 case UiElement::Text::ArtistAlbum:
905 {
906 //优先使用唱片集艺术家,如果为空,则使用艺术家
907 std::wstring artist_display{ CPlayer::GetInstance().GetCurrentSongInfo().album_artist };
908 if (artist_display.empty())
909 artist_display = CPlayer::GetInstance().GetCurrentSongInfo().GetArtist();
910 draw_text = artist_display + L" - " + CPlayer::GetInstance().GetCurrentSongInfo().GetAlbum();
911 } break;
912 case UiElement::Text::Format:
913 draw_text = CPlayerUIBase::GetDisplayFormatString();
914 break;
915 case UiElement::Text::PlayTime:
916 draw_text = CPlayer::GetInstance().GetTimeString();
917 break;
918 case UiElement::Text::PlayTimeAndVolume:
919 if (show_volume)
920 {
921 static const wstring& mute_str = theApp.m_str_table.LoadText(L"UI_TXT_VOLUME_MUTE");
922 int volume = CPlayer::GetInstance().GetVolume();
923 if (volume <= 0)
924 draw_text = theApp.m_str_table.LoadTextFormat(L"UI_TXT_VOLUME", { mute_str, L"" });
925 else
926 draw_text = theApp.m_str_table.LoadTextFormat(L"UI_TXT_VOLUME", { volume, L"%" });
927 }
928 else
929 {
930 draw_text = CPlayer::GetInstance().GetTimeString();
931 }
932 break;
933 default:
934 break;
935 }
936 return draw_text;
937 }
938
Draw()939 void UiElement::AlbumCover::Draw()
940 {
941 CalculateRect();
942 if (show_info)
943 ui->DrawAlbumCoverWithInfo(rect);
944 else
945 ui->DrawAlbumCover(rect);
946 Element::Draw();
947 }
948
CalculateRect()949 void UiElement::AlbumCover::CalculateRect()
950 {
951 Element::CalculateRect();
952 CRect cover_rect{ rect };
953 //如果强制专辑封面为正方形,则在这里计算新的矩形区域
954 if (square)
955 {
956 int side{ min(rect.Width(), rect.Height()) };
957 if (rect.Width() > rect.Height())
958 {
959 cover_rect.left = rect.left + (rect.Width() - side) / 2;
960 cover_rect.right = cover_rect.left + side;
961 }
962 else if (rect.Width() < rect.Height())
963 {
964 cover_rect.top = rect.top + (rect.Height() - side) / 2;
965 cover_rect.bottom = cover_rect.top + side;
966 }
967 rect = cover_rect;
968 }
969 }
970
Draw()971 void UiElement::Spectrum::Draw()
972 {
973 CalculateRect();
974 if (theApp.m_app_setting_data.show_spectrum)
975 {
976 ui->m_draw.DrawSpectrum(rect, type, draw_reflex, theApp.m_app_setting_data.spectrum_low_freq_in_center, fixed_width, align);
977 Element::Draw();
978 }
979 }
980
IsEnable(CRect parent_rect) const981 bool UiElement::Spectrum::IsEnable(CRect parent_rect) const
982 {
983 if (theApp.m_app_setting_data.show_spectrum)
984 return UiElement::Element::IsEnable(parent_rect);
985 return false;
986 }
987
Draw()988 void UiElement::TrackInfo::Draw()
989 {
990 CalculateRect();
991 ui->DrawSongInfo(rect, font_size);
992 Element::Draw();
993 }
994
Draw()995 void UiElement::Toolbar::Draw()
996 {
997 CalculateRect();
998 ui->DrawToolBarWithoutBackground(rect, show_translate_btn);
999 Element::Draw();
1000 }
1001
Draw()1002 void UiElement::ProgressBar::Draw()
1003 {
1004 CalculateRect();
1005 if (show_play_time)
1006 {
1007 ui->DrawProgressBar(rect, play_time_both_side);
1008 }
1009 else
1010 {
1011 ui->DrawProgess(rect);
1012 }
1013 Element::Draw();
1014 }
1015
Draw()1016 void UiElement::Lyrics::Draw()
1017 {
1018 CalculateRect();
1019
1020 bool big_font{ ui->m_ui_data.full_screen && ui->IsDrawLargeIcon() };
1021 CFont* lyric_font = &theApp.m_font_set.lyric.GetFont(big_font);
1022 CFont* lyric_tr_font = &theApp.m_font_set.lyric_translate.GetFont(big_font);
1023
1024 if (use_default_font) // 目前这个bool有些冗余,当字体与字号在m_font_set中解耦后有用
1025 {
1026 lyric_font = &theApp.m_font_set.GetFontBySize(font_size).GetFont(big_font);
1027 lyric_tr_font = &theApp.m_font_set.GetFontBySize(font_size - 1).GetFont(big_font);
1028 }
1029
1030 //如果父元素中包含了矩形元素,则即使在“外观设置”中勾选了“歌词界面背景”,也不再为歌词区域绘制半透明背景
1031 ui->DrawLyrics(rect, lyric_font, lyric_tr_font, (!no_background && !IsParentRectangle()), show_song_info);
1032
1033 ui->m_draw_data.lyric_rect = rect;
1034 Element::Draw();
1035 }
1036
ClearRect()1037 void UiElement::Lyrics::ClearRect()
1038 {
1039 Element::ClearRect();
1040 ui->m_draw_data.lyric_rect = CRect();
1041 }
1042
IsParentRectangle() const1043 bool UiElement::Lyrics::IsParentRectangle() const
1044 {
1045 const Element* ele{ this };
1046 while (ele != nullptr && ele->pParent != nullptr)
1047 {
1048 if (dynamic_cast<const Rectangle*>(ele) != nullptr)
1049 return true;
1050 ele = ele->pParent;
1051 }
1052 return false;
1053 }
1054
Draw()1055 void UiElement::Volume::Draw()
1056 {
1057 CalculateRect();
1058 ui->DrawVolumeButton(rect, adj_btn_on_top, show_text);
1059 Element::Draw();
1060 }
1061
Draw()1062 void UiElement::BeatIndicator::Draw()
1063 {
1064 CalculateRect();
1065 ui->DrawBeatIndicator(rect);
1066 Element::Draw();
1067 }
1068
Draw()1069 void UiElement::ListElement::Draw()
1070 {
1071 CalculateRect();
1072 RestrictOffset();
1073 CalculateItemRects();
1074
1075 if (last_row_count != GetRowCount())
1076 {
1077 OnRowCountChanged();
1078 last_row_count = GetRowCount();
1079 }
1080
1081 ui->DrawList(rect, this, ItemHeight());
1082 Element::Draw();
1083 }
1084
LButtonUp(CPoint point)1085 void UiElement::ListElement::LButtonUp(CPoint point)
1086 {
1087 mouse_pressed = false;
1088 scrollbar_handle_pressed = false;
1089 //设置按钮的按下状态
1090 for (int i{}; i < GetHoverButtonCount(); i++)
1091 {
1092 auto& btn{ GetHoverButtonState(i) };
1093 if (btn.pressed)
1094 {
1095 if (btn.rect.PtInRect(point))
1096 OnHoverButtonClicked(i, GetListIndexByPoint(point));
1097 btn.pressed = false;
1098 }
1099 }
1100 }
1101
LButtonDown(CPoint point)1102 void UiElement::ListElement::LButtonDown(CPoint point)
1103 {
1104 //点击了控件区域
1105 if (rect.PtInRect(point))
1106 {
1107 //点击了滚动条区域
1108 if (scrollbar_rect.PtInRect(point))
1109 {
1110 //点击了滚动条把手区域
1111 if (scrollbar_handle_rect.PtInRect(point))
1112 {
1113 scrollbar_handle_pressed = true;
1114 }
1115 //点击了滚动条空白区域
1116 else
1117 {
1118 mouse_pressed = false;
1119 }
1120 }
1121 //点击了列表区域
1122 else
1123 {
1124 //设置按钮的按下状态
1125 for (int i{}; i < GetHoverButtonCount(); i++)
1126 {
1127 auto& btn{ GetHoverButtonState(i) };
1128 btn.pressed = btn.rect.PtInRect(point);
1129 }
1130
1131 int clicked_index{ GetListIndexByPoint(point) }; //点击的行
1132 //允许多选时
1133 if (IsMultipleSelectionEnable())
1134 {
1135 //是否按下Ctrl键
1136 if (GetKeyState(VK_CONTROL) & 0x80)
1137 {
1138 if (items_selected.contains(clicked_index))
1139 items_selected.erase(clicked_index);
1140 else
1141 items_selected.insert(clicked_index);
1142 }
1143 //是否按下Shift键,并且至少选中了一行
1144 else if (GetKeyState(VK_SHIFT) & 0x8000 && !items_selected.empty())
1145 {
1146 int first_selected = *items_selected.begin(); //选中的第一行
1147 items_selected.clear();
1148 //点击的行在选中的第一行后面
1149 if (first_selected < clicked_index)
1150 {
1151 for (int i = first_selected; i <= clicked_index; i++)
1152 items_selected.insert(i);
1153 }
1154 //点击的行在选中的第一行前面
1155 else
1156 {
1157 for (int i = clicked_index; i <= first_selected; i++)
1158 items_selected.insert(i);
1159 }
1160 }
1161 else
1162 {
1163 SetItemSelected(clicked_index);
1164 }
1165 }
1166 //仅单选时
1167 else
1168 {
1169 SetItemSelected(clicked_index);
1170 }
1171 OnClicked();
1172 selected_item_scroll_info.Reset();
1173 mouse_pressed = true;
1174 }
1175 mouse_pressed_offset = playlist_offset;
1176 mouse_pressed_pos = point;
1177 }
1178 //点击了控件外
1179 else
1180 {
1181 mouse_pressed = false;
1182 //item_selected = -1;
1183 }
1184 }
1185
MouseMove(CPoint point)1186 void UiElement::ListElement::MouseMove(CPoint point)
1187 {
1188 if (rect.IsRectEmpty())
1189 return;
1190
1191 mouse_pos = point;
1192 hover = rect.PtInRect(point);
1193 scrollbar_hover = scrollbar_rect.PtInRect(point);
1194 if (scrollbar_handle_pressed)
1195 {
1196 int delta_scrollbar_offset = mouse_pressed_pos.y - point.y; //滚动条移动的距离
1197 //将滚动条移动的距离转换成播放列表的位移
1198 int scroll_area_height = rect.Height() - scroll_handle_length_comp;
1199 if (scroll_area_height > 0)
1200 {
1201 int delta_playlist_offset = delta_scrollbar_offset * (ItemHeight() * GetDisplayRowCount()) / scroll_area_height;
1202 playlist_offset = mouse_pressed_offset - delta_playlist_offset;
1203 }
1204 }
1205 else if (mouse_pressed)
1206 {
1207 playlist_offset = mouse_pressed_offset + (mouse_pressed_pos.y - point.y);
1208 }
1209
1210 //查找鼠标指向的行
1211 int row = GetListIndexByPoint(point);
1212
1213 //如果显示了按钮
1214 bool mouse_in_btn{ false };
1215 if (GetHoverButtonCount() > 0)
1216 {
1217 for (int i{}; i < GetHoverButtonCount(); i++)
1218 {
1219 auto& btn{ GetHoverButtonState(i) };
1220 if (btn.rect.PtInRect(point) && rect.PtInRect(point))
1221 {
1222 mouse_in_btn = true;
1223 btn.hover = true;
1224 static int last_row{ -1 };
1225 static int last_btn_index{ -1 };
1226 if (last_row != row || last_btn_index != i)
1227 {
1228 std::wstring btn_tooltip{ GetHoverButtonTooltip(i, row) };
1229 ui->UpdateMouseToolTip(GetToolTipIndex(), btn_tooltip.c_str());
1230 ui->UpdateMouseToolTipPosition(GetToolTipIndex(), btn.rect);
1231 }
1232 last_row = row;
1233 last_btn_index = i;
1234 }
1235 else
1236 {
1237 btn.hover = false;
1238 }
1239 }
1240 }
1241
1242 //显示鼠标提示
1243 if (!mouse_in_btn && ShowTooltip() && hover && !scrollbar_hover && !scrollbar_handle_pressed)
1244 {
1245 if (row >= 0)
1246 {
1247 static int last_row{ -1 };
1248 if (last_row != row)
1249 {
1250 last_row = row;
1251 std::wstring str_tip = GetToolTipText(row);
1252
1253 ui->UpdateMouseToolTip(GetToolTipIndex(), str_tip.c_str());
1254 int display_row = row;
1255 AbsoluteRowToDisplayRow(display_row);
1256 if (display_row >= 0 && display_row < static_cast<int>(item_rects.size()))
1257 ui->UpdateMouseToolTipPosition(GetToolTipIndex(), item_rects[display_row]);
1258 }
1259 }
1260 }
1261 }
1262
RButtunUp(CPoint point)1263 bool UiElement::ListElement::RButtunUp(CPoint point)
1264 {
1265 if (rect.PtInRect(point))
1266 {
1267 mouse_pressed = false;
1268 CMenu* menu{ GetContextMenu(GetItemSelected() >= 0 && !scrollbar_rect.PtInRect(point))};
1269 ShowContextMenu(menu, GetCmdRecivedWnd());
1270 return true;
1271 }
1272 return false;
1273 }
1274
ShowContextMenu(CMenu * menu,CWnd * cmd_reciver)1275 void UiElement::ListElement::ShowContextMenu(CMenu* menu, CWnd* cmd_reciver)
1276 {
1277 if (menu != nullptr)
1278 {
1279 CPoint cursor_pos;
1280 GetCursorPos(&cursor_pos);
1281 if (cmd_reciver != nullptr)
1282 {
1283 //弹出右键菜单,当选择了一个菜单命令时向cmd_reciver发送WM_COMMAND消息
1284 menu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, cursor_pos.x, cursor_pos.y, cmd_reciver);
1285 }
1286 else
1287 {
1288 CUIWindowCmdHelper helper(this);
1289 helper.SetMenuState(menu);
1290 //使用TPM_RETURNCMD标志指定菜单命令使用返回值返回,TPM_NONOTIFY标志指定选择了菜单命令后不会向窗口发送WM_COMMAND消息,但是仍然必须传递一个有效的窗口句柄
1291 UINT command = menu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, cursor_pos.x, cursor_pos.y, theApp.m_pMainWnd);
1292 helper.OnUiCommand(command);
1293 }
1294 }
1295 }
1296
1297
RButtonDown(CPoint point)1298 void UiElement::ListElement::RButtonDown(CPoint point)
1299 {
1300 mouse_pressed = false;
1301 if (rect.PtInRect(point))
1302 {
1303 if (!scrollbar_rect.PtInRect(point))
1304 {
1305 int clicked_index{ GetListIndexByPoint(point) }; //点击的行
1306 if (!IsItemSelected(clicked_index))
1307 {
1308 SetItemSelected(clicked_index);
1309 OnClicked();
1310 }
1311 selected_item_scroll_info.Reset();
1312 }
1313 }
1314 else
1315 {
1316 items_selected.clear();
1317 }
1318 }
1319
MouseWheel(int delta,CPoint point)1320 bool UiElement::ListElement::MouseWheel(int delta, CPoint point)
1321 {
1322 if (rect.PtInRect(point))
1323 {
1324 //一次滚动的行数
1325 int lines = rect.Height() / ItemHeight() / 2;
1326 if (lines > 3)
1327 lines = 3;
1328 if (lines < 1)
1329 lines = 1;
1330 playlist_offset += (-delta * lines * ItemHeight() / 120); //120为鼠标滚轮一行时delta的值
1331 return true;
1332 }
1333 return false;
1334 }
1335
MouseLeave()1336 void UiElement::ListElement::MouseLeave()
1337 {
1338 hover = false;
1339 mouse_pressed = false;
1340 scrollbar_hover = false;
1341 scrollbar_handle_pressed = false;
1342 }
1343
DoubleClick(CPoint point)1344 bool UiElement::ListElement::DoubleClick(CPoint point)
1345 {
1346 if (rect.PtInRect(point) && !scrollbar_rect.PtInRect(point) && GetItemSelected() >= 0)
1347 {
1348 OnDoubleClicked();
1349 }
1350 return false;
1351 }
1352
ClearRect()1353 void UiElement::ListElement::ClearRect()
1354 {
1355 Element::ClearRect();
1356 for (auto& btn : hover_buttons)
1357 btn.second.rect = CRect();
1358 }
1359
EnsureItemVisible(int index)1360 void UiElement::ListElement::EnsureItemVisible(int index)
1361 {
1362 if (index <= 0)
1363 {
1364 playlist_offset = 0;
1365 return;
1366 }
1367
1368 CalculateRect();
1369 CalculateItemRects();
1370
1371 AbsoluteRowToDisplayRow(index);
1372 if (index < 0 || index >= static_cast<int>(item_rects.size()))
1373 return;
1374
1375 CRect item_rect{ item_rects[index] };
1376 //确定当前项目是否处于可见状态
1377 if (item_rect.top > rect.top && item_rect.bottom < rect.bottom)
1378 return;
1379
1380 //计算要使指定项可见时的偏移量
1381 int delta_offset{};
1382 //指定项目在播放列表上方
1383 if (item_rect.top < rect.top)
1384 delta_offset = rect.top - item_rect.top;
1385 //指定项目在播放列表下方
1386 else if (item_rect.bottom > rect.bottom)
1387 delta_offset = rect.bottom - item_rect.bottom;
1388 playlist_offset -= delta_offset;
1389 }
1390
EnsureHighlightItemVisible()1391 void UiElement::ListElement::EnsureHighlightItemVisible()
1392 {
1393 int highlight_row{ GetHighlightRow() };
1394 if (highlight_row >= 0)
1395 EnsureItemVisible(highlight_row);
1396 }
1397
RestrictOffset()1398 void UiElement::ListElement::RestrictOffset()
1399 {
1400 int& offset{ playlist_offset };
1401 if (offset < 0)
1402 offset = 0;
1403 int offset_max{ ItemHeight() * GetDisplayRowCount() - rect.Height() };
1404 if (offset_max <= 0)
1405 offset = 0;
1406 else if (offset > offset_max)
1407 offset = offset_max;
1408 }
1409
CalculateItemRects()1410 void UiElement::ListElement::CalculateItemRects()
1411 {
1412 item_rects.resize(GetRowCount());
1413 for (size_t i{}; i < item_rects.size(); i++)
1414 {
1415 //计算每一行的矩形区域
1416 int start_y = -playlist_offset + rect.top + i * ItemHeight();
1417 CRect rect_item{ rect };
1418 rect_item.top = start_y;
1419 rect_item.bottom = rect_item.top + ItemHeight();
1420
1421 //保存每一行的矩形区域
1422 item_rects[i] = rect_item;
1423 }
1424 }
1425
ItemHeight() const1426 int UiElement::ListElement::ItemHeight() const
1427 {
1428 return ui->DPI(item_height);
1429 }
1430
SetItemSelected(int index)1431 void UiElement::ListElement::SetItemSelected(int index)
1432 {
1433 items_selected.clear();
1434 if (index >= 0)
1435 {
1436 items_selected.insert(index);
1437 EnsureItemVisible(index);
1438 }
1439 }
1440
GetItemSelected() const1441 int UiElement::ListElement::GetItemSelected() const
1442 {
1443 if (!items_selected.empty())
1444 return *items_selected.begin();
1445 return -1;
1446 }
1447
SetItemsSelected(const vector<int> & indexes)1448 void UiElement::ListElement::SetItemsSelected(const vector<int>& indexes)
1449 {
1450 items_selected.clear();
1451 for (int index : indexes)
1452 items_selected.insert(index);
1453 }
1454
GetItemsSelected(vector<int> & indexes) const1455 void UiElement::ListElement::GetItemsSelected(vector<int>& indexes) const
1456 {
1457 indexes.clear();
1458 for (int index : items_selected)
1459 indexes.push_back(index);
1460 }
1461
IsItemSelected(int index) const1462 bool UiElement::ListElement::IsItemSelected(int index) const
1463 {
1464 auto iter = std::find(items_selected.begin(), items_selected.end(), index);
1465 return iter != items_selected.end();
1466 }
1467
IsMultipleSelected() const1468 bool UiElement::ListElement::IsMultipleSelected() const
1469 {
1470 return items_selected.size() > 1;
1471 }
1472
SelectAll()1473 void UiElement::ListElement::SelectAll()
1474 {
1475 if (IsMultipleSelectionEnable())
1476 {
1477 items_selected.clear();
1478 for (int i{}; i < GetRowCount(); i++)
1479 items_selected.insert(i);
1480 }
1481 }
1482
SelectNone()1483 void UiElement::ListElement::SelectNone()
1484 {
1485 items_selected.clear();
1486 }
1487
SelectReversed()1488 void UiElement::ListElement::SelectReversed()
1489 {
1490 if (IsMultipleSelectionEnable())
1491 {
1492 auto items_selected_old{ items_selected };
1493 items_selected.clear();
1494 for (int i{}; i < GetRowCount(); i++)
1495 {
1496 if (!items_selected_old.contains(i))
1497 items_selected.insert(i);
1498 }
1499 }
1500 }
1501
GetHoverButtonState(int btn_index)1502 IPlayerUI::UIButton& UiElement::ListElement::GetHoverButtonState(int btn_index)
1503 {
1504 return hover_buttons[btn_index];
1505 }
1506
OnRowCountChanged()1507 void UiElement::ListElement::OnRowCountChanged()
1508 {
1509 //如果列表的行数有变化,则清除选中
1510 SelectNone();
1511 //清除搜索框
1512 if (related_search_box != nullptr)
1513 related_search_box->Clear();
1514 }
1515
QuickSearch(const std::wstring & key_word)1516 void UiElement::ListElement::QuickSearch(const std::wstring& key_word)
1517 {
1518 searched = !key_word.empty();
1519
1520 //查找匹配的序号
1521 search_result.clear();
1522 if (key_word.empty())
1523 return;
1524 for (int i = 0; i < GetRowCount(); i++)
1525 {
1526 if (IsItemMatchKeyWord(i, key_word))
1527 search_result.push_back(i);
1528 }
1529 }
1530
IsItemMatchKeyWord(int row,const std::wstring & key_word)1531 bool UiElement::ListElement::IsItemMatchKeyWord(int row, const std::wstring& key_word)
1532 {
1533 bool rtn = false;
1534 //默认匹配每一列中的文本
1535 for (int i = 0; i < GetColumnCount(); i++)
1536 {
1537 std::wstring text = GetItemText(row, i);
1538 if (!text.empty() && theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, text))
1539 return true;
1540 }
1541 return false;
1542 }
1543
GetDisplayRowCount()1544 int UiElement::ListElement::GetDisplayRowCount()
1545 {
1546 if (searched)
1547 return search_result.size();
1548 else
1549 return GetRowCount();
1550 }
1551
IsRowDisplayed(int row)1552 bool UiElement::ListElement::IsRowDisplayed(int row)
1553 {
1554 if (row >= 0 && row < GetRowCount())
1555 {
1556 //搜索状态下,仅搜索结果中的行显示
1557 if (searched)
1558 {
1559 return CCommon::IsItemInVector(search_result, row);
1560 }
1561 //非搜索状态下,所有行都显示
1562 else
1563 {
1564 return true;
1565 }
1566 }
1567 return false;
1568 }
1569
DisplayRowToAbsoluteRow(int & row)1570 void UiElement::ListElement::DisplayRowToAbsoluteRow(int& row)
1571 {
1572 if (searched) //查找状态下需要转换行号
1573 {
1574 if (row >= 0 && row < static_cast<int>(search_result.size()))
1575 row = search_result[row];
1576 else
1577 row = -1;
1578 }
1579 }
1580
AbsoluteRowToDisplayRow(int & row)1581 void UiElement::ListElement::AbsoluteRowToDisplayRow(int& row)
1582 {
1583 if (searched) //查找状态下需要转换行号
1584 {
1585 bool row_exist{};
1586 for (int i{}; i < static_cast<int>(search_result.size()); i++)
1587 {
1588 if (row == search_result[i])
1589 {
1590 row = i;
1591 row_exist = true;
1592 break;
1593 }
1594 }
1595 if (!row_exist)
1596 row = -1;
1597 }
1598 }
1599
GetListIndexByPoint(CPoint point)1600 int UiElement::ListElement::GetListIndexByPoint(CPoint point)
1601 {
1602 int index = GetDisplayedIndexByPoint(point);
1603 DisplayRowToAbsoluteRow(index);
1604 return index;
1605 }
1606
GetDisplayedIndexByPoint(CPoint point)1607 int UiElement::ListElement::GetDisplayedIndexByPoint(CPoint point)
1608 {
1609 for (size_t i{}; i < item_rects.size(); i++)
1610 {
1611 if (item_rects[i].PtInRect(point))
1612 return static_cast<int>(i);
1613 }
1614 return -1;
1615 }
1616
GetItemText(int row,int col)1617 std::wstring UiElement::Playlist::GetItemText(int row, int col)
1618 {
1619 if (row >= 0 && row < GetRowCount())
1620 {
1621 //序号
1622 if (col == COL_INDEX)
1623 {
1624 return std::to_wstring(row + 1);
1625 }
1626 //曲目
1627 else if (col == COL_TRACK)
1628 {
1629 const SongInfo& song_info{ CPlayer::GetInstance().GetPlayList()[row] };
1630 std::wstring display_name{ CSongInfoHelper::GetDisplayStr(song_info, theApp.m_media_lib_setting_data.display_format) };
1631 return display_name;
1632 }
1633 //时间
1634 else if (col == COL_TIME)
1635 {
1636 const SongInfo& song_info{ CPlayer::GetInstance().GetPlayList()[row] };
1637 return song_info.length().toString();
1638 }
1639 }
1640
1641 return std::wstring();
1642 }
1643
GetColumnCount()1644 int UiElement::Playlist::GetColumnCount()
1645 {
1646 return COL_MAX;
1647 }
1648
GetColumnWidth(int col,int total_width)1649 int UiElement::Playlist::GetColumnWidth(int col, int total_width)
1650 {
1651 const int index_width{ ui->DPI(40) };
1652 const int time_width{ ui->DPI(50) };
1653 if (col == COL_INDEX)
1654 {
1655 return index_width;
1656 }
1657 else if (col == COL_TIME)
1658 {
1659 return time_width;
1660 }
1661 else if (col == COL_TRACK)
1662 {
1663 return total_width - index_width - time_width;
1664 }
1665 return 0;
1666 }
1667
GetEmptyString()1668 std::wstring UiElement::Playlist::GetEmptyString()
1669 {
1670 const wstring& info = theApp.m_str_table.LoadText(L"UI_PLAYLIST_EMPTY_INFO");
1671 return info;
1672 }
1673
GetHighlightRow()1674 int UiElement::Playlist::GetHighlightRow()
1675 {
1676 int highlight_row = CPlayer::GetInstance().GetIndex();
1677 if (last_highlight_row != highlight_row)
1678 {
1679 EnsureItemVisible(highlight_row);
1680 last_highlight_row = highlight_row;
1681 }
1682 return highlight_row;
1683 }
1684
GetColumnScrollTextWhenSelected()1685 int UiElement::Playlist::GetColumnScrollTextWhenSelected()
1686 {
1687 return COL_TRACK;
1688 }
1689
ShowTooltip()1690 bool UiElement::Playlist::ShowTooltip()
1691 {
1692 return theApp.m_media_lib_setting_data.show_playlist_tooltip;
1693 }
1694
GetToolTipText(int row)1695 std::wstring UiElement::Playlist::GetToolTipText(int row)
1696 {
1697 if (row >= 0 && row < CPlayer::GetInstance().GetSongNum())
1698 {
1699 const SongInfo& song_info = CPlayer::GetInstance().GetPlayList()[row];
1700 bool show_full_path = (!CPlayer::GetInstance().IsFolderMode() || CPlayer::GetInstance().IsContainSubFolder());
1701 std::wstring str_tip = CSongInfoHelper::GetPlaylistItemToolTip(song_info, true, show_full_path);
1702 return str_tip;
1703 }
1704
1705 return std::wstring();
1706 }
1707
GetToolTipIndex() const1708 int UiElement::Playlist::GetToolTipIndex() const
1709 {
1710 return TooltipIndex::PLAYLIST;
1711 }
1712
GetContextMenu(bool item_selected)1713 CMenu* UiElement::Playlist::GetContextMenu(bool item_selected)
1714 {
1715 if (item_selected)
1716 return theApp.m_menu_mgr.GetMenu(MenuMgr::PlaylistMenu);
1717 else
1718 return theApp.m_menu_mgr.GetMenu(MenuMgr::PlaylistToolBarMenu);
1719 return nullptr;
1720 }
1721
GetCmdRecivedWnd()1722 CWnd* UiElement::Playlist::GetCmdRecivedWnd()
1723 {
1724 //Playlist中的右键菜单命令在主窗口中响应
1725 return theApp.m_pMainWnd;
1726 }
1727
OnDoubleClicked()1728 void UiElement::Playlist::OnDoubleClicked()
1729 {
1730 ::SendMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_COMMAND, ID_PLAY_ITEM, 0);
1731 }
1732
OnClicked()1733 void UiElement::Playlist::OnClicked()
1734 {
1735 CMusicPlayerDlg* pMainWnd = CMusicPlayerDlg::GetInstance();
1736 if (pMainWnd != nullptr)
1737 {
1738 std::vector<int> indexes;
1739 GetItemsSelected(indexes);
1740 pMainWnd->SetPlaylistSelected(indexes);
1741 }
1742 }
1743
GetHoverButtonCount()1744 int UiElement::Playlist::GetHoverButtonCount()
1745 {
1746 return BTN_MAX;
1747 }
1748
GetHoverButtonColumn()1749 int UiElement::Playlist::GetHoverButtonColumn()
1750 {
1751 return COL_TRACK;
1752 }
1753
GetHoverButtonIcon(int index,int row)1754 IconMgr::IconType UiElement::Playlist::GetHoverButtonIcon(int index, int row)
1755 {
1756 switch (index)
1757 {
1758 case BTN_PLAY: return IconMgr::IT_Play;
1759 case BTN_ADD: return IconMgr::IT_Add;
1760 case BTN_FAVOURITE:
1761 {
1762 if (CPlayer::GetInstance().IsFavourite(row))
1763 return IconMgr::IT_Favorite_Off;
1764 else
1765 return IconMgr::IT_Favorite_On;
1766 }
1767 }
1768 return IconMgr::IT_NO_ICON;
1769 }
1770
GetHoverButtonTooltip(int index,int row)1771 std::wstring UiElement::Playlist::GetHoverButtonTooltip(int index, int row)
1772 {
1773 switch (index)
1774 {
1775 case BTN_PLAY: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
1776 case BTN_ADD: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_ADD_TO_PLAYLIST");
1777 case BTN_FAVOURITE: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_FAVOURITE");
1778 }
1779 return std::wstring();
1780 }
1781
OnHoverButtonClicked(int btn_index,int row)1782 void UiElement::Playlist::OnHoverButtonClicked(int btn_index, int row)
1783 {
1784 CMusicPlayerCmdHelper helper;
1785 //点击了“播放”按钮
1786 if (btn_index == BTN_PLAY)
1787 {
1788 helper.OnPlayTrack(row);
1789 }
1790 //点击了“添加到播放列表”按钮
1791 else if (btn_index == BTN_ADD)
1792 {
1793 CMenu* menu = theApp.m_menu_mgr.GetMenu(MenuMgr::AddToPlaylistMenu);
1794 ShowContextMenu(menu, nullptr);
1795 }
1796 //点击了“添加到我喜欢的音乐”按钮
1797 else if (btn_index == BTN_FAVOURITE)
1798 {
1799 helper.OnAddRemoveFromFavourite(row);
1800 }
1801 }
1802
GetUnHoverIconCount(int row)1803 int UiElement::Playlist::GetUnHoverIconCount(int row)
1804 {
1805 //鼠标未指向的列,如果曲目在“我喜欢的音乐”中,则显示红心图标
1806 if (CPlayer::GetInstance().IsFavourite(row))
1807 return 1;
1808 else
1809 return 0;
1810 }
1811
GetUnHoverIcon(int index,int row)1812 IconMgr::IconType UiElement::Playlist::GetUnHoverIcon(int index, int row)
1813 {
1814 if (index == 0)
1815 {
1816 return IconMgr::IT_Favorite_Off;
1817 }
1818 return IconMgr::IT_NO_ICON;
1819 }
1820
OnRowCountChanged()1821 void UiElement::Playlist::OnRowCountChanged()
1822 {
1823 ListElement::OnRowCountChanged();
1824 //播放列表行数改变时,通知主窗口取消播放列表选中项
1825 ::SendMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_COMMAND, ID_PLAYLIST_SELECT_NONE, 0);
1826 }
1827
IsItemMatchKeyWord(int row,const std::wstring & key_word)1828 bool UiElement::Playlist::IsItemMatchKeyWord(int row, const std::wstring& key_word)
1829 {
1830 if (row >= 0 && row < CPlayer::GetInstance().GetSongNum())
1831 {
1832 const SongInfo& song_info = CPlayer::GetInstance().GetPlayList()[row];
1833 return (theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, song_info.GetFileName())
1834 || theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, song_info.title)
1835 || theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, song_info.artist)
1836 || theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, song_info.album));
1837 }
1838 return false;
1839 }
1840
GetRowCount()1841 int UiElement::Playlist::GetRowCount()
1842 {
1843 int song_num{ CPlayer::GetInstance().GetSongNum() };
1844 if (song_num == 1 && CPlayer::GetInstance().GetPlayList()[0].IsEmpty()) //不显示播放列表为空时的占位符
1845 song_num = 0;
1846 return song_num;
1847 }
1848
1849 CListCache UiElement::RecentPlayedList::m_list_cache(LT_RECENT);
1850
Draw()1851 void UiElement::RecentPlayedList::Draw()
1852 {
1853 m_list_cache.reload();
1854 ListElement::Draw();
1855 }
1856
GetItemText(int row,int col)1857 std::wstring UiElement::RecentPlayedList::GetItemText(int row, int col)
1858 {
1859 if (row >= 0 && row < GetRowCount())
1860 {
1861 if (col == COL_NAME)
1862 {
1863 return m_list_cache.at(row).GetDisplayName();
1864 }
1865 else if (col == COL_COUNT)
1866 {
1867 return std::to_wstring(m_list_cache.at(row).total_num);
1868 }
1869 }
1870 return std::wstring();
1871 }
1872
GetRowCount()1873 int UiElement::RecentPlayedList::GetRowCount()
1874 {
1875 return m_list_cache.size();
1876 }
1877
GetColumnCount()1878 int UiElement::RecentPlayedList::GetColumnCount()
1879 {
1880 return COL_MAX;
1881 }
1882
GetColumnWidth(int col,int total_width)1883 int UiElement::RecentPlayedList::GetColumnWidth(int col, int total_width)
1884 {
1885 const int count_width{ ui->DPI(40) };
1886 if (col == COL_NAME)
1887 return total_width - count_width;
1888 else if (col == COL_COUNT)
1889 return count_width;
1890 return 0;
1891 }
1892
GetColumnScrollTextWhenSelected()1893 int UiElement::RecentPlayedList::GetColumnScrollTextWhenSelected()
1894 {
1895 return COL_NAME;
1896 }
1897
GetIcon(int row)1898 IconMgr::IconType UiElement::RecentPlayedList::GetIcon(int row)
1899 {
1900 if (row >= 0 && row < GetRowCount())
1901 {
1902 return m_list_cache.at(row).GetTypeIcon();
1903 }
1904 return IconMgr::IT_NO_ICON;
1905 }
1906
HasIcon()1907 bool UiElement::RecentPlayedList::HasIcon()
1908 {
1909 return true;
1910 }
1911
OnDoubleClicked()1912 void UiElement::RecentPlayedList::OnDoubleClicked()
1913 {
1914 int sel_index = GetItemSelected();
1915 CMusicPlayerCmdHelper helper;
1916 helper.OnListItemSelected(m_list_cache.GetItem(sel_index), true);
1917 }
1918
GetContextMenu(bool item_selected)1919 CMenu* UiElement::RecentPlayedList::GetContextMenu(bool item_selected)
1920 {
1921 if (item_selected)
1922 {
1923 return theApp.m_menu_mgr.GetMenu(MenuMgr::UiRecentPlayedMenu);
1924 }
1925 return nullptr;
1926 }
1927
GetHoverButtonCount()1928 int UiElement::RecentPlayedList::GetHoverButtonCount()
1929 {
1930 return 1;
1931 }
1932
GetHoverButtonColumn()1933 int UiElement::RecentPlayedList::GetHoverButtonColumn()
1934 {
1935 return COL_NAME;
1936 }
1937
GetHoverButtonIcon(int index,int row)1938 IconMgr::IconType UiElement::RecentPlayedList::GetHoverButtonIcon(int index, int row)
1939 {
1940 if (index == 0)
1941 return IconMgr::IT_Play;
1942 return IconMgr::IT_NO_ICON;
1943 }
1944
GetHoverButtonTooltip(int index,int row)1945 std::wstring UiElement::RecentPlayedList::GetHoverButtonTooltip(int index, int row)
1946 {
1947 if (index == 0)
1948 return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
1949 return std::wstring();
1950 }
1951
OnHoverButtonClicked(int btn_index,int row)1952 void UiElement::RecentPlayedList::OnHoverButtonClicked(int btn_index, int row)
1953 {
1954 CMusicPlayerCmdHelper helper;
1955 //点击了“播放”按钮
1956 if (btn_index == 0)
1957 {
1958 if (row >= 0 && row < GetRowCount())
1959 {
1960 CMusicPlayerCmdHelper helper;
1961 helper.OnListItemSelected(m_list_cache.GetItem(row), true);
1962 }
1963 }
1964 }
1965
GetItemText(int row,int col)1966 std::wstring UiElement::MediaLibItemList::GetItemText(int row, int col)
1967 {
1968 if (col == COL_NAME)
1969 {
1970 if (row >= 0 && row < CUiMediaLibItemMgr::Instance().GetItemCount(type))
1971 return CUiMediaLibItemMgr::Instance().GetItemDisplayName(type, row);
1972 }
1973 else if (col == COL_COUNT)
1974 {
1975 if (row >= 0 && row < CUiMediaLibItemMgr::Instance().GetItemCount(type))
1976 return std::to_wstring(CUiMediaLibItemMgr::Instance().GetItemSongCount(type, row));
1977 }
1978 return std::wstring();
1979 }
1980
GetRowCount()1981 int UiElement::MediaLibItemList::GetRowCount()
1982 {
1983 return CUiMediaLibItemMgr::Instance().GetItemCount(type);
1984 }
1985
GetColumnCount()1986 int UiElement::MediaLibItemList::GetColumnCount()
1987 {
1988 return COL_MAX;
1989 }
1990
GetColumnWidth(int col,int total_width)1991 int UiElement::MediaLibItemList::GetColumnWidth(int col, int total_width)
1992 {
1993 const int count_width{ ui->DPI(40) };
1994 if (col == COL_NAME)
1995 return total_width - count_width;
1996 else if (col == COL_COUNT)
1997 return count_width;
1998 return 0;
1999 }
2000
GetEmptyString()2001 std::wstring UiElement::MediaLibItemList::GetEmptyString()
2002 {
2003 if (CUiMediaLibItemMgr::Instance().IsLoading())
2004 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_LOADING_INFO");
2005 else if (!CUiMediaLibItemMgr::Instance().IsInited())
2006 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_UNINITED_INFO");
2007 else
2008 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_EMPTY_INFO");
2009 }
2010
GetHighlightRow()2011 int UiElement::MediaLibItemList::GetHighlightRow()
2012 {
2013 if (CPlayer::GetInstance().IsMediaLibMode() && CPlayer::GetInstance().GetMediaLibPlaylistType() == type)
2014 {
2015 int highlight_row = CUiMediaLibItemMgr::Instance().GetCurrentIndex(type);
2016 if (last_highlight_row != highlight_row)
2017 {
2018 EnsureItemVisible(highlight_row);
2019 last_highlight_row = highlight_row;
2020 }
2021 return highlight_row;
2022 }
2023 return -1;
2024 }
2025
GetColumnScrollTextWhenSelected()2026 int UiElement::MediaLibItemList::GetColumnScrollTextWhenSelected()
2027 {
2028 return COL_NAME;
2029 }
2030
GetContextMenu(bool item_selected)2031 CMenu* UiElement::MediaLibItemList::GetContextMenu(bool item_selected)
2032 {
2033 if (item_selected)
2034 {
2035 return theApp.m_menu_mgr.GetMenu(MenuMgr::UiLibLeftMenu);
2036 }
2037 return nullptr;
2038 }
2039
OnDoubleClicked()2040 void UiElement::MediaLibItemList::OnDoubleClicked()
2041 {
2042 int item_selected = GetItemSelected();
2043 if (item_selected >= 0 && item_selected < CUiMediaLibItemMgr::Instance().GetItemCount(type))
2044 {
2045 std::wstring item_name = CUiMediaLibItemMgr::Instance().GetItemName(type, item_selected);
2046 CMusicPlayerCmdHelper helper;
2047 ListItem list_item{ LT_MEDIA_LIB, item_name, type };
2048 helper.OnListItemSelected(list_item, true);
2049 }
2050 }
2051
GetHoverButtonCount()2052 int UiElement::MediaLibItemList::GetHoverButtonCount()
2053 {
2054 return BTN_MAX;
2055 }
2056
GetHoverButtonColumn()2057 int UiElement::MediaLibItemList::GetHoverButtonColumn()
2058 {
2059 return COL_NAME;
2060 }
2061
GetHoverButtonIcon(int index,int row)2062 IconMgr::IconType UiElement::MediaLibItemList::GetHoverButtonIcon(int index, int row)
2063 {
2064 switch (index)
2065 {
2066 case BTN_PLAY: return IconMgr::IT_Play;
2067 case BTN_ADD: return IconMgr::IT_Add;
2068 }
2069 return IconMgr::IT_NO_ICON;
2070 }
2071
GetHoverButtonTooltip(int index,int row)2072 std::wstring UiElement::MediaLibItemList::GetHoverButtonTooltip(int index, int row)
2073 {
2074 switch (index)
2075 {
2076 case BTN_PLAY: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
2077 case BTN_ADD: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_ADD_TO_PLAYLIST");
2078 }
2079 return std::wstring();
2080 }
2081
OnHoverButtonClicked(int btn_index,int row)2082 void UiElement::MediaLibItemList::OnHoverButtonClicked(int btn_index, int row)
2083 {
2084 CMusicPlayerCmdHelper helper;
2085 //点击了“播放”按钮
2086 if (btn_index == BTN_PLAY)
2087 {
2088 int item_selected = GetItemSelected();
2089 if (item_selected >= 0 && item_selected < GetRowCount())
2090 {
2091 std::wstring item_name = CUiMediaLibItemMgr::Instance().GetItemName(type, item_selected);
2092 CMusicPlayerCmdHelper helper;
2093 ListItem list_item{ LT_MEDIA_LIB, item_name, type };
2094 helper.OnListItemSelected(list_item, true);
2095 }
2096 }
2097 //点击了“添加到播放列表”按钮
2098 else if (btn_index == BTN_ADD)
2099 {
2100 CMenu* menu = theApp.m_menu_mgr.GetMenu(MenuMgr::AddToPlaylistMenu);
2101 ShowContextMenu(menu, nullptr);
2102 }
2103 }
2104
2105 CListCache UiElement::PlaylistIndicator::m_list_cache(LT_CURRENT);
2106
Draw()2107 void UiElement::PlaylistIndicator::Draw()
2108 {
2109 m_list_cache.reload();
2110 CalculateRect();
2111 ui->DrawCurrentPlaylistIndicator(rect, this);
2112 Element::Draw();
2113 }
2114
LButtonUp(CPoint point)2115 void UiElement::PlaylistIndicator::LButtonUp(CPoint point)
2116 {
2117 if (btn_drop_down.rect.PtInRect(point))
2118 {
2119 btn_drop_down.hover = false;
2120 CRect btn_rect = rect_name;
2121 AfxGetMainWnd()->ClientToScreen(&btn_rect);
2122 theApp.m_menu_mgr.GetMenu(MenuMgr::RecentFolderPlaylistMenu)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, btn_rect.left, btn_rect.bottom, AfxGetMainWnd());
2123 }
2124 else if (btn_menu.rect.PtInRect(point))
2125 {
2126 btn_menu.hover = false;
2127 CRect btn_rect = btn_menu.rect;
2128 AfxGetMainWnd()->ClientToScreen(&btn_rect);
2129 theApp.m_menu_mgr.GetMenu(MenuMgr::PlaylistToolBarMenu)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, btn_rect.left, btn_rect.bottom, AfxGetMainWnd());
2130 }
2131 btn_drop_down.pressed = false;
2132 btn_menu.pressed = false;
2133 }
2134
LButtonDown(CPoint point)2135 void UiElement::PlaylistIndicator::LButtonDown(CPoint point)
2136 {
2137 btn_drop_down.pressed = (btn_drop_down.rect.PtInRect(point) != FALSE);
2138 btn_menu.pressed = (btn_menu.rect.PtInRect(point) != FALSE);
2139 }
2140
MouseMove(CPoint point)2141 void UiElement::PlaylistIndicator::MouseMove(CPoint point)
2142 {
2143 btn_drop_down.hover = (btn_drop_down.rect.PtInRect(point) != FALSE);
2144 btn_menu.hover = (btn_menu.rect.PtInRect(point) != FALSE);
2145
2146 if (btn_drop_down.hover)
2147 ui->UpdateMouseToolTipPosition(TooltipIndex::PLAYLIST_DROP_DOWN_BTN, btn_drop_down.rect);
2148 if (btn_menu.hover)
2149 ui->UpdateMouseToolTipPosition(TooltipIndex::PLAYLIST_MENU_BTN, btn_menu.rect);
2150 }
2151
MouseLeave()2152 void UiElement::PlaylistIndicator::MouseLeave()
2153 {
2154 btn_drop_down.pressed = false;
2155 btn_drop_down.hover = false;
2156 btn_menu.pressed = false;
2157 btn_menu.hover = false;
2158 }
2159
ClearRect()2160 void UiElement::PlaylistIndicator::ClearRect()
2161 {
2162 Element::ClearRect();
2163 btn_drop_down.rect = CRect();
2164 btn_menu.rect = CRect();
2165 }
2166
ClassicalControlBar()2167 UiElement::ClassicalControlBar::ClassicalControlBar()
2168 : Element()
2169 {
2170 max_height.FromString("56");
2171 }
2172
Draw()2173 void UiElement::ClassicalControlBar::Draw()
2174 {
2175 if (rect.Width() < ui->m_progress_on_top_threshold)
2176 max_height.FromString("56");
2177 else
2178 max_height.FromString("36");
2179 CalculateRect();
2180
2181 ui->DrawControlBar(rect, show_switch_display_btn);
2182 Element::Draw();
2183 }
2184
Draw()2185 void UiElement::NavigationBar::Draw()
2186 {
2187 CalculateRect();
2188 ui->DrawNavigationBar(rect, this);
2189 Element::Draw();
2190 }
2191
LButtonUp(CPoint point)2192 void UiElement::NavigationBar::LButtonUp(CPoint point)
2193 {
2194 FindStackElement();
2195 if (stack_element != nullptr)
2196 {
2197 //查找点击的标签
2198 int _selected_index = -1;
2199 for (size_t i{}; i < item_rects.size(); i++)
2200 {
2201 if (item_rects[i].PtInRect(point))
2202 {
2203 _selected_index = i;
2204 break;
2205 }
2206 }
2207 if (_selected_index >= 0)
2208 {
2209 selected_index = _selected_index;
2210 stack_element->SetCurrentElement(selected_index);
2211 }
2212 }
2213 }
2214
MouseMove(CPoint point)2215 void UiElement::NavigationBar::MouseMove(CPoint point)
2216 {
2217 int _hover_index{ -1 };
2218 if (rect.PtInRect(point))
2219 {
2220 for (size_t i{}; i < item_rects.size(); i++)
2221 {
2222 if (item_rects[i].PtInRect(point))
2223 {
2224 _hover_index = i;
2225 break;
2226 }
2227 }
2228 }
2229 hover_index = _hover_index;
2230
2231 //显示鼠标提示
2232 if (icon_type == ICON_ONLY && hover_index >= 0)
2233 {
2234 if (last_hover_index != hover_index)
2235 {
2236 last_hover_index = hover_index;
2237 std::wstring str_tip = labels[hover_index];
2238 ui->UpdateMouseToolTip(TooltipIndex::TAB_ELEMENT, str_tip.c_str());
2239 ui->UpdateMouseToolTipPosition(TooltipIndex::TAB_ELEMENT, item_rects[hover_index]);
2240 }
2241 }
2242 }
2243
RButtunUp(CPoint point)2244 bool UiElement::NavigationBar::RButtunUp(CPoint point)
2245 {
2246 //不弹出右键菜单
2247 return rect.PtInRect(point);
2248 }
2249
MouseLeave()2250 void UiElement::NavigationBar::MouseLeave()
2251 {
2252 hover_index = -1;
2253 }
2254
SelectedIndex()2255 int UiElement::NavigationBar::SelectedIndex()
2256 {
2257 FindStackElement();
2258 if (stack_element != nullptr)
2259 return stack_element->GetCurIndex();
2260 else
2261 return selected_index;
2262 }
2263
FindStackElement()2264 void UiElement::NavigationBar::FindStackElement()
2265 {
2266 if (!find_stack_element)
2267 {
2268 stack_element = FindRelatedElement<StackElement>(this);
2269 find_stack_element = true; //找过一次没找到就不找了
2270 }
2271 }
2272
2273 CListCache UiElement::MediaLibFolder::m_list_cache(LT_FOLDER);
2274
Draw()2275 void UiElement::MediaLibFolder::Draw()
2276 {
2277 m_list_cache.reload();
2278 ListElement::Draw();
2279 }
2280
GetItemText(int row,int col)2281 std::wstring UiElement::MediaLibFolder::GetItemText(int row, int col)
2282 {
2283 if (col == COL_NAME)
2284 {
2285 return m_list_cache.at(row).path;
2286 }
2287 else if (col == COL_COUNT)
2288 {
2289 return std::to_wstring(m_list_cache.at(row).total_num);
2290 }
2291 return std::wstring();
2292 }
2293
GetRowCount()2294 int UiElement::MediaLibFolder::GetRowCount()
2295 {
2296 return m_list_cache.size();
2297 }
2298
GetColumnCount()2299 int UiElement::MediaLibFolder::GetColumnCount()
2300 {
2301 return COL_MAX;
2302 }
2303
GetColumnWidth(int col,int total_width)2304 int UiElement::MediaLibFolder::GetColumnWidth(int col, int total_width)
2305 {
2306 const int count_width{ ui->DPI(40) };
2307 if (col == COL_NAME)
2308 return total_width - count_width;
2309 else if (col == COL_COUNT)
2310 return count_width;
2311 return 0;
2312 }
2313
GetHighlightRow()2314 int UiElement::MediaLibFolder::GetHighlightRow()
2315 {
2316 return m_list_cache.playing_index();
2317 }
2318
GetColumnScrollTextWhenSelected()2319 int UiElement::MediaLibFolder::GetColumnScrollTextWhenSelected()
2320 {
2321 return COL_NAME;
2322 }
2323
GetContextMenu(bool item_selected)2324 CMenu* UiElement::MediaLibFolder::GetContextMenu(bool item_selected)
2325 {
2326 return theApp.m_menu_mgr.GetMenu(MenuMgr::LibSetPathMenu);
2327 }
2328
OnDoubleClicked()2329 void UiElement::MediaLibFolder::OnDoubleClicked()
2330 {
2331 int item_selected = GetItemSelected();
2332 if (item_selected >= 0 && item_selected < GetRowCount())
2333 {
2334 ListItem list_item = m_list_cache.GetItem(item_selected);
2335 CMusicPlayerCmdHelper helper;
2336 helper.OnListItemSelected(list_item, true);
2337 }
2338 }
2339
GetHoverButtonCount()2340 int UiElement::MediaLibFolder::GetHoverButtonCount()
2341 {
2342 return BTN_MAX;
2343 }
2344
GetHoverButtonColumn()2345 int UiElement::MediaLibFolder::GetHoverButtonColumn()
2346 {
2347 return COL_NAME;
2348 }
2349
GetHoverButtonIcon(int index,int row)2350 IconMgr::IconType UiElement::MediaLibFolder::GetHoverButtonIcon(int index, int row)
2351 {
2352 switch (index)
2353 {
2354 case BTN_PLAY: return IconMgr::IT_Play;
2355 case BTN_ADD: return IconMgr::IT_Add;
2356 }
2357 return IconMgr::IT_NO_ICON;
2358 }
2359
GetHoverButtonTooltip(int index,int row)2360 std::wstring UiElement::MediaLibFolder::GetHoverButtonTooltip(int index, int row)
2361 {
2362 switch (index)
2363 {
2364 case BTN_PLAY: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
2365 case BTN_ADD: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_ADD_TO_PLAYLIST");
2366 }
2367 return std::wstring();
2368 }
2369
OnHoverButtonClicked(int btn_index,int row)2370 void UiElement::MediaLibFolder::OnHoverButtonClicked(int btn_index, int row)
2371 {
2372 //点击了“播放”按钮
2373 if (btn_index == BTN_PLAY)
2374 {
2375 if (row >= 0 && row < GetRowCount())
2376 {
2377 ListItem list_item = m_list_cache.GetItem(row);
2378 CMusicPlayerCmdHelper helper;
2379 helper.OnListItemSelected(list_item, true);
2380 }
2381 }
2382 //点击了“添加到播放列表”按钮
2383 else if (btn_index == BTN_ADD)
2384 {
2385 CMenu* menu = theApp.m_menu_mgr.GetMenu(MenuMgr::AddToPlaylistMenu);
2386 ShowContextMenu(menu, nullptr);
2387 }
2388 }
2389
2390 CListCache UiElement::MediaLibPlaylist::m_list_cache(LT_PLAYLIST);
2391
Draw()2392 void UiElement::MediaLibPlaylist::Draw()
2393 {
2394 m_list_cache.reload();
2395 ListElement::Draw();
2396 }
2397
GetItemText(int row,int col)2398 std::wstring UiElement::MediaLibPlaylist::GetItemText(int row, int col)
2399 {
2400 if (col == COL_NAME)
2401 {
2402 return m_list_cache.at(row).GetDisplayName();
2403 }
2404 else if (col == COL_COUNT)
2405 {
2406 return std::to_wstring(m_list_cache.at(row).total_num);
2407 }
2408 return std::wstring();
2409 }
2410
GetRowCount()2411 int UiElement::MediaLibPlaylist::GetRowCount()
2412 {
2413 return m_list_cache.size();
2414 }
2415
GetColumnCount()2416 int UiElement::MediaLibPlaylist::GetColumnCount()
2417 {
2418 return COL_MAX;
2419 }
2420
GetColumnWidth(int col,int total_width)2421 int UiElement::MediaLibPlaylist::GetColumnWidth(int col, int total_width)
2422 {
2423 const int count_width{ ui->DPI(40) };
2424 if (col == COL_NAME)
2425 return total_width - count_width;
2426 else if (col == COL_COUNT)
2427 return count_width;
2428 return 0;
2429 }
2430
GetHighlightRow()2431 int UiElement::MediaLibPlaylist::GetHighlightRow()
2432 {
2433 return m_list_cache.playing_index();
2434 }
2435
GetColumnScrollTextWhenSelected()2436 int UiElement::MediaLibPlaylist::GetColumnScrollTextWhenSelected()
2437 {
2438 return COL_NAME;
2439 }
2440
GetContextMenu(bool item_selected)2441 CMenu* UiElement::MediaLibPlaylist::GetContextMenu(bool item_selected)
2442 {
2443 return theApp.m_menu_mgr.GetMenu(MenuMgr::LibPlaylistMenu);
2444 }
2445
OnDoubleClicked()2446 void UiElement::MediaLibPlaylist::OnDoubleClicked()
2447 {
2448 int item_selected = GetItemSelected();
2449 ListItem list_item = m_list_cache.GetItem(item_selected);
2450 if (!list_item.empty())
2451 {
2452 CMusicPlayerCmdHelper helper;
2453 helper.OnListItemSelected(list_item, true);
2454 }
2455 }
2456
GetHoverButtonCount()2457 int UiElement::MediaLibPlaylist::GetHoverButtonCount()
2458 {
2459 return 1;
2460 }
2461
GetHoverButtonColumn()2462 int UiElement::MediaLibPlaylist::GetHoverButtonColumn()
2463 {
2464 return COL_NAME;
2465 }
2466
GetHoverButtonIcon(int index,int row)2467 IconMgr::IconType UiElement::MediaLibPlaylist::GetHoverButtonIcon(int index, int row)
2468 {
2469 if (index == 0)
2470 return IconMgr::IT_Play;
2471 return IconMgr::IT_NO_ICON;
2472 }
2473
GetHoverButtonTooltip(int index,int row)2474 std::wstring UiElement::MediaLibPlaylist::GetHoverButtonTooltip(int index, int row)
2475 {
2476 if (index == 0)
2477 return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
2478 return std::wstring();
2479 }
2480
OnHoverButtonClicked(int btn_index,int row)2481 void UiElement::MediaLibPlaylist::OnHoverButtonClicked(int btn_index, int row)
2482 {
2483 //点击了“播放”按钮
2484 if (btn_index == 0)
2485 {
2486 ListItem list_item = m_list_cache.GetItem(row);
2487 if (!list_item.empty())
2488 {
2489 CMusicPlayerCmdHelper helper;
2490 helper.OnListItemSelected(list_item, true);
2491 }
2492 }
2493 }
2494
GetItemText(int row,int col)2495 std::wstring UiElement::MyFavouriteList::GetItemText(int row, int col)
2496 {
2497 if (row >= 0 && row < GetRowCount())
2498 {
2499 //序号
2500 if (col == COL_INDEX)
2501 {
2502 return std::to_wstring(row + 1);
2503 }
2504 //曲目
2505 if (col == COL_TRACK)
2506 {
2507 if (row >= 0 && row < CUiMyFavouriteItemMgr::Instance().GetSongCount())
2508 {
2509 const SongInfo& song_info{ CUiMyFavouriteItemMgr::Instance().GetSongInfo(row) };
2510 std::wstring display_name{ CSongInfoHelper::GetDisplayStr(song_info, theApp.m_media_lib_setting_data.display_format) };
2511 return display_name;
2512 }
2513 }
2514 //时间
2515 else if (col == COL_TIME)
2516 {
2517 const SongInfo& song_info{ CUiMyFavouriteItemMgr::Instance().GetSongInfo(row) };
2518 return song_info.length().toString();
2519 }
2520 }
2521 return std::wstring();
2522 }
2523
GetRowCount()2524 int UiElement::MyFavouriteList::GetRowCount()
2525 {
2526 return CUiMyFavouriteItemMgr::Instance().GetSongCount();
2527 }
2528
GetColumnCount()2529 int UiElement::MyFavouriteList::GetColumnCount()
2530 {
2531 return COL_MAX;
2532 }
2533
GetColumnWidth(int col,int total_width)2534 int UiElement::MyFavouriteList::GetColumnWidth(int col, int total_width)
2535 {
2536 const int index_width{ ui->DPI(40) };
2537 const int time_width{ ui->DPI(50) };
2538 if (col == COL_INDEX)
2539 {
2540 return index_width;
2541 }
2542 else if (col == COL_TIME)
2543 {
2544 return time_width;
2545 }
2546 else if (col == COL_TRACK)
2547 {
2548 return total_width - index_width - time_width;
2549 }
2550 return 0;
2551 }
2552
GetHighlightRow()2553 int UiElement::MyFavouriteList::GetHighlightRow()
2554 {
2555 if (CRecentList::Instance().IsPlayingSpecPlaylist(CRecentList::PT_FAVOURITE))
2556 {
2557 return CPlayer::GetInstance().GetIndex();
2558 }
2559 return -1;
2560 }
2561
GetColumnScrollTextWhenSelected()2562 int UiElement::MyFavouriteList::GetColumnScrollTextWhenSelected()
2563 {
2564 return COL_TRACK;
2565 }
2566
GetContextMenu(bool item_selected)2567 CMenu* UiElement::MyFavouriteList::GetContextMenu(bool item_selected)
2568 {
2569 if (item_selected)
2570 {
2571 return theApp.m_menu_mgr.GetMenu(MenuMgr::UiMyFavouriteMenu);
2572 }
2573 return nullptr;
2574 }
2575
OnDoubleClicked()2576 void UiElement::MyFavouriteList::OnDoubleClicked()
2577 {
2578 int item_selected = GetItemSelected();
2579 if (item_selected >= 0 && item_selected < GetRowCount())
2580 {
2581 CMusicPlayerCmdHelper helper;
2582 SongInfo song_info{ CUiMyFavouriteItemMgr::Instance().GetSongInfo(item_selected) };
2583 helper.OnPlayMyFavourite(song_info);
2584 }
2585 }
2586
GetEmptyString()2587 std::wstring UiElement::MyFavouriteList::GetEmptyString()
2588 {
2589 if (CUiMyFavouriteItemMgr::Instance().IsLoading())
2590 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_LOADING_INFO");
2591 else if (!CUiMyFavouriteItemMgr::Instance().IsInited())
2592 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_UNINITED_INFO");
2593 else
2594 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_EMPTY_INFO");
2595 }
2596
GetHoverButtonCount()2597 int UiElement::MyFavouriteList::GetHoverButtonCount()
2598 {
2599 return BTN_MAX;
2600 }
2601
GetHoverButtonColumn()2602 int UiElement::MyFavouriteList::GetHoverButtonColumn()
2603 {
2604 return COL_TRACK;
2605 }
2606
GetHoverButtonIcon(int index,int row)2607 IconMgr::IconType UiElement::MyFavouriteList::GetHoverButtonIcon(int index, int row)
2608 {
2609 switch (index)
2610 {
2611 case BTN_PLAY: return IconMgr::IT_Play;
2612 case BTN_ADD: return IconMgr::IT_Add;
2613 }
2614 return IconMgr::IT_NO_ICON;
2615 }
2616
GetHoverButtonTooltip(int index,int row)2617 std::wstring UiElement::MyFavouriteList::GetHoverButtonTooltip(int index, int row)
2618 {
2619 switch (index)
2620 {
2621 case BTN_PLAY: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
2622 case BTN_ADD: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_ADD_TO_PLAYLIST");
2623 }
2624 return std::wstring();
2625 }
2626
OnHoverButtonClicked(int btn_index,int row)2627 void UiElement::MyFavouriteList::OnHoverButtonClicked(int btn_index, int row)
2628 {
2629 CMusicPlayerCmdHelper helper;
2630 //点击了“播放”按钮
2631 if (btn_index == BTN_PLAY)
2632 {
2633 int item_selected = GetItemSelected();
2634 if (item_selected >= 0 && item_selected < GetRowCount())
2635 {
2636 CMusicPlayerCmdHelper helper;
2637 SongInfo song_info{ CUiMyFavouriteItemMgr::Instance().GetSongInfo(item_selected) };
2638 helper.OnPlayMyFavourite(song_info);
2639 }
2640 }
2641 //点击了“添加到播放列表”按钮
2642 else if (btn_index == BTN_ADD)
2643 {
2644 CMenu* menu = theApp.m_menu_mgr.GetMenu(MenuMgr::AddToPlaylistMenu);
2645 ShowContextMenu(menu, nullptr);
2646 }
2647 }
2648
IsMultipleSelectionEnable()2649 bool UiElement::MyFavouriteList::IsMultipleSelectionEnable()
2650 {
2651 return true;
2652 }
2653
GetItemText(int row,int col)2654 std::wstring UiElement::AllTracksList::GetItemText(int row, int col)
2655 {
2656 if (row >= 0 && row < GetRowCount())
2657 {
2658 //序号
2659 if (col == COL_INDEX)
2660 {
2661 return std::to_wstring(row + 1);
2662 }
2663 //曲目
2664 if (col == COL_TRACK)
2665 {
2666 if (row >= 0 && row < CUiAllTracksMgr::Instance().GetSongCount())
2667 {
2668 return CUiAllTracksMgr::Instance().GetItem(row).name;
2669 }
2670 }
2671 //时间
2672 else if (col == COL_TIME)
2673 {
2674 if (row >= 0 && row < CUiAllTracksMgr::Instance().GetSongCount())
2675 {
2676 return CUiAllTracksMgr::Instance().GetItem(row).length.toString();
2677 }
2678 }
2679 }
2680 return std::wstring();
2681 }
2682
GetRowCount()2683 int UiElement::AllTracksList::GetRowCount()
2684 {
2685 return CUiAllTracksMgr::Instance().GetSongCount();
2686 }
2687
GetColumnCount()2688 int UiElement::AllTracksList::GetColumnCount()
2689 {
2690 return COL_MAX;
2691 }
2692
GetColumnWidth(int col,int total_width)2693 int UiElement::AllTracksList::GetColumnWidth(int col, int total_width)
2694 {
2695 const int index_width{ ui->DPI(40) };
2696 const int time_width{ ui->DPI(50) };
2697 if (col == COL_INDEX)
2698 {
2699 return index_width;
2700 }
2701 else if (col == COL_TIME)
2702 {
2703 return time_width;
2704 }
2705 else if (col == COL_TRACK)
2706 {
2707 return total_width - index_width - time_width;
2708 }
2709 return 0;
2710 }
2711
GetHighlightRow()2712 int UiElement::AllTracksList::GetHighlightRow()
2713 {
2714 int highlight_row = CUiAllTracksMgr::Instance().GetCurrentIndex();
2715 if (last_highlight_row != highlight_row)
2716 {
2717 EnsureItemVisible(highlight_row);
2718 last_highlight_row = highlight_row;
2719 }
2720 return highlight_row;
2721 }
2722
GetColumnScrollTextWhenSelected()2723 int UiElement::AllTracksList::GetColumnScrollTextWhenSelected()
2724 {
2725 return COL_TRACK;
2726 }
2727
GetContextMenu(bool item_selected)2728 CMenu* UiElement::AllTracksList::GetContextMenu(bool item_selected)
2729 {
2730 if (item_selected)
2731 {
2732 return theApp.m_menu_mgr.GetMenu(MenuMgr::LibRightMenu);
2733 }
2734 return nullptr;
2735 }
2736
OnDoubleClicked()2737 void UiElement::AllTracksList::OnDoubleClicked()
2738 {
2739 int item_selected = GetItemSelected();
2740 if (item_selected >= 0 && item_selected < GetRowCount())
2741 {
2742 const SongInfo& song{ CUiAllTracksMgr::Instance().GetSongInfo(item_selected) };
2743 CMusicPlayerCmdHelper helper;
2744 helper.OnPlayAllTrack(song);
2745 }
2746 }
2747
GetEmptyString()2748 std::wstring UiElement::AllTracksList::GetEmptyString()
2749 {
2750 if (CUiAllTracksMgr::Instance().IsLoading())
2751 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_LOADING_INFO");
2752 else if (!CUiAllTracksMgr::Instance().IsInited())
2753 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_UNINITED_INFO");
2754 else
2755 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_EMPTY_INFO");
2756 }
2757
GetHoverButtonCount()2758 int UiElement::AllTracksList::GetHoverButtonCount()
2759 {
2760 return BTN_MAX;
2761 }
2762
GetHoverButtonColumn()2763 int UiElement::AllTracksList::GetHoverButtonColumn()
2764 {
2765 return COL_TRACK;
2766 }
2767
GetHoverButtonIcon(int index,int row)2768 IconMgr::IconType UiElement::AllTracksList::GetHoverButtonIcon(int index, int row)
2769 {
2770 switch (index)
2771 {
2772 case BTN_PLAY: return IconMgr::IT_Play;
2773 case BTN_ADD: return IconMgr::IT_Add;
2774 case BTN_FAVOURITE:
2775 {
2776 if (CUiAllTracksMgr::Instance().GetItem(row).is_favourite)
2777 return IconMgr::IT_Favorite_Off;
2778 else
2779 return IconMgr::IT_Favorite_On;
2780 }
2781 }
2782 return IconMgr::IT_NO_ICON;
2783 }
2784
GetHoverButtonTooltip(int index,int row)2785 std::wstring UiElement::AllTracksList::GetHoverButtonTooltip(int index, int row)
2786 {
2787 switch (index)
2788 {
2789 case BTN_PLAY: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
2790 case BTN_ADD: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_ADD_TO_PLAYLIST");
2791 case BTN_FAVOURITE: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_FAVOURITE");
2792 }
2793 return std::wstring();
2794 }
2795
OnHoverButtonClicked(int btn_index,int row)2796 void UiElement::AllTracksList::OnHoverButtonClicked(int btn_index, int row)
2797 {
2798 CMusicPlayerCmdHelper helper;
2799 //点击了“播放”按钮
2800 if (btn_index == BTN_PLAY)
2801 {
2802 const SongInfo& song{ CUiAllTracksMgr::Instance().GetSongInfo(row) };
2803 CMusicPlayerCmdHelper helper;
2804 helper.OnPlayAllTrack(song);
2805 }
2806 //点击了“添加到播放列表”按钮
2807 else if (btn_index == BTN_ADD)
2808 {
2809 CMenu* menu = theApp.m_menu_mgr.GetMenu(MenuMgr::AddToPlaylistMenu);
2810 ShowContextMenu(menu, nullptr);
2811 }
2812 //点击了“添加到我喜欢的音乐”按钮
2813 else if (btn_index == BTN_FAVOURITE)
2814 {
2815 const SongInfo& song{ CUiAllTracksMgr::Instance().GetSongInfo(row) };
2816 helper.OnAddRemoveFromFavourite(song);
2817 CUiAllTracksMgr::Instance().AddOrRemoveMyFavourite(row); //更新UI中的显示
2818 }
2819 }
2820
GetUnHoverIconCount(int row)2821 int UiElement::AllTracksList::GetUnHoverIconCount(int row)
2822 {
2823 //鼠标未指向的列,如果曲目在“我喜欢的音乐”中,则显示红心图标
2824 if (CUiAllTracksMgr::Instance().GetItem(row).is_favourite)
2825 return 1;
2826 else
2827 return 0;
2828 }
2829
GetUnHoverIcon(int index,int row)2830 IconMgr::IconType UiElement::AllTracksList::GetUnHoverIcon(int index, int row)
2831 {
2832 if (index == 0)
2833 {
2834 return IconMgr::IT_Favorite_Off;
2835 }
2836 return IconMgr::IT_NO_ICON;
2837 }
2838
IsMultipleSelectionEnable()2839 bool UiElement::AllTracksList::IsMultipleSelectionEnable()
2840 {
2841 return true;
2842 }
2843
Draw()2844 void UiElement::MiniSpectrum::Draw()
2845 {
2846 CalculateRect();
2847 ui->DrawMiniSpectrum(rect);
2848 Element::Draw();
2849 }
2850
GetWidth(CRect parent_rect) const2851 int UiElement::PlaceHolder::GetWidth(CRect parent_rect) const
2852 {
2853 if (IsHide())
2854 {
2855 return 0;
2856 }
2857 else
2858 {
2859 if (show_when_use_system_titlebar)
2860 return ui->TopRightButtonsWidth();
2861 else
2862 return Element::GetWidth(parent_rect);
2863 }
2864 }
2865
GetHeight(CRect parent_rect) const2866 int UiElement::PlaceHolder::GetHeight(CRect parent_rect) const
2867 {
2868 if (IsHide())
2869 return 0;
2870 else
2871 return Element::GetHeight(parent_rect);
2872 }
2873
IsWidthValid() const2874 bool UiElement::PlaceHolder::IsWidthValid() const
2875 {
2876 if (show_when_use_system_titlebar)
2877 return true;
2878 return Element::IsWidthValid();
2879 }
2880
IsHide() const2881 bool UiElement::PlaceHolder::IsHide() const
2882 {
2883 //标题栏中的图标除了最小化和最大化/还原外是否都隐藏
2884 bool is_all_titlebar_icon_hide = !theApp.m_app_setting_data.show_minimode_btn_in_titlebar
2885 && !theApp.m_app_setting_data.show_fullscreen_btn_in_titlebar
2886 && !theApp.m_app_setting_data.show_skin_btn_in_titlebar
2887 && !theApp.m_app_setting_data.show_settings_btn_in_titlebar
2888 && !theApp.m_app_setting_data.show_dark_light_btn_in_titlebar
2889 ;
2890 //如果设置了“仅当使用系统标准标题栏时才显示”,并且没有使用系统标准标题栏,则不显示
2891 return (show_when_use_system_titlebar
2892 && !theApp.m_app_setting_data.show_window_frame
2893 && (!theApp.m_ui_data.full_screen) || (theApp.m_ui_data.show_menu_bar && is_all_titlebar_icon_hide));
2894 }
2895
AddChild(std::shared_ptr<Node> child)2896 void UiElement::TreeElement::Node::AddChild(std::shared_ptr<Node> child)
2897 {
2898 child->parent = this;
2899 child_list.push_back(child);
2900 }
2901
GetLevel() const2902 int UiElement::TreeElement::Node::GetLevel() const
2903 {
2904 int level{};
2905 const Node* node{ this };
2906 while (node != nullptr && node->parent != nullptr)
2907 {
2908 node = node->parent;
2909 level++;
2910 }
2911 return level;
2912 }
2913
IterateNodeInOrder(std::function<bool (Node *)> func,bool ignore_invisible)2914 void UiElement::TreeElement::Node::IterateNodeInOrder(std::function<bool(Node*)> func, bool ignore_invisible)
2915 {
2916 std::stack<UiElement::TreeElement::Node*> nodeStack;
2917 nodeStack.push(this);
2918 while (!nodeStack.empty())
2919 {
2920 UiElement::TreeElement::Node* pCurNode = nodeStack.top();
2921 nodeStack.pop();
2922
2923 if (func(pCurNode))
2924 break;
2925
2926 //如果当前节点已经折叠,且需要忽略已折叠的节点,则不再遍历其子节点
2927 if (pCurNode->collapsed && ignore_invisible)
2928 continue;
2929
2930 for (auto& child : pCurNode->child_list)
2931 {
2932 nodeStack.push(child.get());
2933 }
2934 }
2935 }
2936
GetItemText(int row,int col)2937 std::wstring UiElement::TreeElement::GetItemText(int row, int col)
2938 {
2939 //查找节点
2940 const Node* node = GetNodeByIndex(row);
2941 if (node != nullptr)
2942 {
2943 auto iter = node->texts.find(col);
2944 if (iter != node->texts.end())
2945 return iter->second;
2946 }
2947 return std::wstring();
2948 }
2949
GetRowCount()2950 int UiElement::TreeElement::GetRowCount()
2951 {
2952 int row_count{};
2953 IterateDisplayedNodeInOrder([&](const Node*) ->bool {
2954 row_count++;
2955 return false;
2956 });
2957 return row_count;
2958 }
2959
QuickSearch(const std::wstring & key_word)2960 void UiElement::TreeElement::QuickSearch(const std::wstring& key_word)
2961 {
2962 tree_searched = !key_word.empty();
2963
2964 tree_search_result.clear();
2965 if (key_word.empty())
2966 return;
2967 //遍历所有节点,获取匹配的节点,并添加到tree_search_result中
2968 auto& root_nodes{ GetRootNodes() };
2969 for (auto& root : root_nodes)
2970 {
2971 root->IterateNodeInOrder([&](Node* cur_node) ->bool {
2972 if (IsNodeMathcKeyWord(cur_node, key_word))
2973 {
2974 tree_search_result.insert(cur_node);
2975 cur_node->collapsed = false; //匹配的节点全部展开
2976 }
2977 return false;
2978 }, false);
2979 }
2980 }
2981
OnRowCountChanged()2982 void UiElement::TreeElement::OnRowCountChanged()
2983 {
2984 //树控件的行数变化可能只是节点的展开或折叠,因此不执行基类中OnRowCountChanged的处理。
2985 }
2986
GetItemLevel(int row)2987 int UiElement::TreeElement::GetItemLevel(int row)
2988 {
2989 const Node* node = GetNodeByIndex(row);
2990 if (node != nullptr)
2991 return node->GetLevel();
2992 return 0;
2993 }
2994
IsCollapsable(int row)2995 bool UiElement::TreeElement::IsCollapsable(int row)
2996 {
2997 const Node* node = GetNodeByIndex(row);
2998 if (node != nullptr)
2999 return !node->child_list.empty();
3000 return false;
3001 }
3002
IsCollapsed(int row)3003 bool UiElement::TreeElement::IsCollapsed(int row)
3004 {
3005 const Node* node = GetNodeByIndex(row);
3006 if (node != nullptr)
3007 return node->collapsed;
3008 return false;
3009 }
3010
LButtonUp(CPoint point)3011 void UiElement::TreeElement::LButtonUp(CPoint point)
3012 {
3013 //获取点击的行
3014 int row = GetListIndexByPoint(point);
3015 if (row >= 0)
3016 {
3017 auto iter = collapsd_rects.find(row);
3018 if (iter != collapsd_rects.end())
3019 {
3020 CRect rect_collapsd = iter->second;
3021 //点击了折叠标志
3022 if (rect_collapsd.PtInRect(point))
3023 {
3024 Node* node = GetNodeByIndex(row);
3025 node->collapsed = !node->collapsed;
3026 }
3027 }
3028 }
3029
3030 ListElement::LButtonUp(point);
3031 }
3032
MouseMove(CPoint point)3033 void UiElement::TreeElement::MouseMove(CPoint point)
3034 {
3035 //获取鼠标指向的行
3036 int row = GetListIndexByPoint(point);
3037 collaps_indicator_hover_row = -1;
3038 if (row >= 0)
3039 {
3040 auto iter = collapsd_rects.find(row);
3041 if (iter != collapsd_rects.end())
3042 {
3043 CRect rect_collapsd = iter->second;
3044 //指向了折叠标志
3045 if (rect_collapsd.PtInRect(point))
3046 {
3047 collaps_indicator_hover_row = row;
3048 }
3049 }
3050 }
3051
3052 ListElement::MouseMove(point);
3053 }
3054
MouseLeave()3055 void UiElement::TreeElement::MouseLeave()
3056 {
3057 collaps_indicator_hover_row = -1;
3058 ListElement::MouseLeave();
3059 }
3060
DoubleClick(CPoint point)3061 bool UiElement::TreeElement::DoubleClick(CPoint point)
3062 {
3063 //如果双击了折叠标志,则不执行双击动作
3064 for (const auto& rect : collapsd_rects)
3065 {
3066 if (rect.second.PtInRect(point))
3067 return false;
3068 }
3069 return ListElement::DoubleClick(point);
3070 }
3071
GetNodeIndex(const Node * node)3072 int UiElement::TreeElement::GetNodeIndex(const Node* node)
3073 {
3074 int i{};
3075 int rtn_index{ -1 };
3076 IterateDisplayedNodeInOrder([&](const Node* cur_node) ->bool {
3077 if (cur_node == node)
3078 {
3079 rtn_index = i;
3080 return true;
3081 }
3082 i++;
3083 return false;
3084 });
3085
3086 return rtn_index;
3087 }
3088
GetNodeByIndex(int index)3089 UiElement::TreeElement::Node* UiElement::TreeElement::GetNodeByIndex(int index)
3090 {
3091 if (index >= 0)
3092 {
3093 Node* find_node{};
3094 int i{};
3095 IterateDisplayedNodeInOrder([&](Node* cur_node) ->bool {
3096 if (i == index)
3097 {
3098 find_node = cur_node;
3099 return true;
3100 }
3101 i++;
3102 return false;
3103 });
3104 return find_node;
3105 }
3106
3107 return nullptr;
3108 }
3109
IsNodeMathcKeyWord(const Node * node,const std::wstring & key_word)3110 bool UiElement::TreeElement::IsNodeMathcKeyWord(const Node* node, const std::wstring& key_word)
3111 {
3112 //判断节点本身是否匹配
3113 for (const auto& item : node->texts)
3114 {
3115 const std::wstring& text{ item.second };
3116 if (!text.empty() && theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, text))
3117 return true;
3118 }
3119
3120 //如果节点本身不匹配,则遍历所有子节点,如果有一个子节点匹配,则节点匹配
3121 for (const auto& child : node->child_list)
3122 {
3123 if (IsNodeMathcKeyWord(child.get(), key_word))
3124 return true;
3125 }
3126
3127 return false;
3128 }
3129
IsNodeDisplayed(const Node * node)3130 bool UiElement::TreeElement::IsNodeDisplayed(const Node* node)
3131 {
3132 if (node != nullptr)
3133 {
3134 if (tree_searched)
3135 return tree_search_result.contains(node);
3136 else
3137 return true;
3138 }
3139 return false;
3140 }
3141
IterateDisplayedNodeInOrder(std::function<bool (Node *)> func)3142 void UiElement::TreeElement::IterateDisplayedNodeInOrder(std::function<bool(Node*)> func)
3143 {
3144 const auto& root_nodes{ GetRootNodes() };
3145 for (const auto& root : root_nodes)
3146 {
3147 bool exit{};
3148 root->IterateNodeInOrder([&](Node* cur_node) ->bool {
3149 if (IsNodeDisplayed(cur_node))
3150 {
3151 if (func(cur_node))
3152 {
3153 exit = true;
3154 return true;
3155 }
3156 }
3157 return false;
3158 }, true);
3159 if (exit)
3160 break;
3161 }
3162 }
3163
TestTree()3164 UiElement::TestTree::TestTree()
3165 {
3166 //创建测试节点
3167 std::shared_ptr<Node> root1 = CreateNode(L"根节点1", nullptr);
3168 std::shared_ptr<Node> root2 = CreateNode(L"根节点2", nullptr);
3169
3170 CreateNode(L"子节点11", root1);
3171 auto node12 = CreateNode(L"子节点12", root1);
3172
3173 CreateNode(L"子节点121", node12);
3174 CreateNode(L"子节点122", node12);
3175
3176 CreateNode(L"子节点21", root2);
3177 CreateNode(L"子节点22", root2);
3178
3179 root_nodes.push_back(root1);
3180 root_nodes.push_back(root2);
3181 }
3182
CreateNode(std::wstring name,std::shared_ptr<Node> parent)3183 std::shared_ptr<UiElement::TreeElement::Node> UiElement::TestTree::CreateNode(std::wstring name, std::shared_ptr<Node> parent)
3184 {
3185 std::shared_ptr<Node> node = std::make_shared<Node>();
3186 node->collapsed = true;
3187 node->texts[0] = name;
3188 if (parent != nullptr)
3189 parent->AddChild(node);
3190 return node;
3191 }
3192
GetColumnCount()3193 int UiElement::TestTree::GetColumnCount()
3194 {
3195 return 1;
3196 }
3197
GetColumnWidth(int col,int total_width)3198 int UiElement::TestTree::GetColumnWidth(int col, int total_width)
3199 {
3200 return total_width;
3201 }
3202
GetRootNodes()3203 std::vector<std::shared_ptr<UiElement::TestTree::Node>>& UiElement::TestTree::GetRootNodes()
3204 {
3205 return root_nodes;
3206 }
3207
CreateNode(std::wstring name,int song_num,std::shared_ptr<Node> parent)3208 std::shared_ptr<UiElement::TestTree::Node> UiElement::FolderExploreTree::CreateNode(std::wstring name, int song_num, std::shared_ptr<Node> parent)
3209 {
3210 std::shared_ptr<Node> node = std::make_shared<Node>();
3211 node->collapsed = true;
3212 node->texts[COL_NAME] = name;
3213 node->texts[COL_COUNT] = std::to_wstring(song_num);
3214 if (parent != nullptr)
3215 parent->AddChild(node);
3216 return node;
3217 }
3218
GetNodePath(Node * node)3219 std::wstring UiElement::FolderExploreTree::GetNodePath(Node* node)
3220 {
3221 std::wstring path{ node->texts[COL_NAME] };
3222 Node* cur_node{ node };
3223 while (cur_node != nullptr && cur_node->parent != nullptr)
3224 {
3225 cur_node = cur_node->parent;
3226 std::wstring parent_name = cur_node->texts[COL_NAME];
3227 if (!parent_name.empty() && parent_name.back() != L'\\' && parent_name.back() != L'/')
3228 parent_name.push_back(L'\\');
3229 path = parent_name + path;
3230 }
3231
3232 return path;
3233 }
3234
GetSelectedPath()3235 std::wstring UiElement::FolderExploreTree::GetSelectedPath()
3236 {
3237 int item_selected = GetItemSelected();
3238 if (item_selected >= 0 && item_selected < GetRowCount())
3239 {
3240 auto selected_node = GetNodeByIndex(item_selected);
3241 if (selected_node != nullptr)
3242 return GetNodePath(selected_node);
3243 }
3244 return std::wstring();
3245 }
3246
GetColumnCount()3247 int UiElement::FolderExploreTree::GetColumnCount()
3248 {
3249 return COL_MAX;
3250 }
3251
GetColumnWidth(int col,int total_width)3252 int UiElement::FolderExploreTree::GetColumnWidth(int col, int total_width)
3253 {
3254 const int count_width{ ui->DPI(40) };
3255 if (col == COL_NAME)
3256 return total_width - count_width;
3257 else if (col == COL_COUNT)
3258 return count_width;
3259 return 0;
3260 }
3261
GetColumnScrollTextWhenSelected()3262 int UiElement::FolderExploreTree::GetColumnScrollTextWhenSelected()
3263 {
3264 return COL_NAME;
3265 }
3266
GetContextMenu(bool item_selected)3267 CMenu* UiElement::FolderExploreTree::GetContextMenu(bool item_selected)
3268 {
3269 if (item_selected)
3270 {
3271 return theApp.m_menu_mgr.GetMenu(MenuMgr::LibFolderExploreMenu);
3272 }
3273 return nullptr;
3274 }
3275
OnDoubleClicked()3276 void UiElement::FolderExploreTree::OnDoubleClicked()
3277 {
3278 int item_selected = GetItemSelected();
3279 if (item_selected >= 0 && item_selected < GetRowCount())
3280 {
3281 auto selected_node = GetNodeByIndex(item_selected);
3282 if (selected_node != nullptr)
3283 {
3284 std::wstring folder_path = GetNodePath(selected_node);
3285 CMusicPlayerCmdHelper helper;
3286 helper.OnOpenFolder(folder_path, true, true);
3287 }
3288 }
3289 }
3290
GetEmptyString()3291 std::wstring UiElement::FolderExploreTree::GetEmptyString()
3292 {
3293 if (CUiFolderExploreMgr::Instance().IsLoading())
3294 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_LOADING_INFO");
3295 else if (!CUiFolderExploreMgr::Instance().IsInited())
3296 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_UNINITED_INFO");
3297 else
3298 return theApp.m_str_table.LoadText(L"UI_MEDIALIB_LIST_EMPTY_INFO");
3299 }
3300
GetHoverButtonCount()3301 int UiElement::FolderExploreTree::GetHoverButtonCount()
3302 {
3303 return BTN_MAX;
3304 }
3305
GetHoverButtonColumn()3306 int UiElement::FolderExploreTree::GetHoverButtonColumn()
3307 {
3308 return COL_NAME;
3309 }
3310
GetHoverButtonIcon(int index,int row)3311 IconMgr::IconType UiElement::FolderExploreTree::GetHoverButtonIcon(int index, int row)
3312 {
3313 switch (index)
3314 {
3315 case BTN_PLAY: return IconMgr::IT_Play;
3316 case BTN_ADD: return IconMgr::IT_Add;
3317 }
3318 return IconMgr::IT_NO_ICON;
3319 }
3320
GetHoverButtonTooltip(int index,int row)3321 std::wstring UiElement::FolderExploreTree::GetHoverButtonTooltip(int index, int row)
3322 {
3323 switch (index)
3324 {
3325 case BTN_PLAY: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_PLAY");
3326 case BTN_ADD: return theApp.m_str_table.LoadText(L"UI_TIP_BTN_ADD_TO_PLAYLIST");
3327 }
3328 return std::wstring();
3329 }
3330
OnHoverButtonClicked(int btn_index,int row)3331 void UiElement::FolderExploreTree::OnHoverButtonClicked(int btn_index, int row)
3332 {
3333 CMusicPlayerCmdHelper helper;
3334 //点击了“播放”按钮
3335 if (btn_index == 0)
3336 {
3337 if (row >= 0 && row < GetRowCount())
3338 {
3339 auto selected_node = GetNodeByIndex(row);
3340 if (selected_node != nullptr)
3341 {
3342 std::wstring folder_path = GetNodePath(selected_node);
3343 CMusicPlayerCmdHelper helper;
3344 helper.OnOpenFolder(folder_path, true, true);
3345 }
3346 }
3347 }
3348 //点击了“添加到播放列表”按钮
3349 else if (btn_index == BTN_ADD)
3350 {
3351 CMenu* menu = theApp.m_menu_mgr.GetMenu(MenuMgr::AddToPlaylistMenu);
3352 ShowContextMenu(menu, nullptr);
3353 }
3354 }
3355
IsMultipleSelectionEnable()3356 bool UiElement::FolderExploreTree::IsMultipleSelectionEnable()
3357 {
3358 return false;
3359 }
3360
GetRootNodes()3361 std::vector<std::shared_ptr<UiElement::TestTree::Node>>& UiElement::FolderExploreTree::GetRootNodes()
3362 {
3363 return CUiFolderExploreMgr::Instance().GetRootNodes();
3364 }
3365
SearchBox()3366 UiElement::SearchBox::SearchBox()
3367 {
3368 }
3369
~SearchBox()3370 UiElement::SearchBox::~SearchBox()
3371 {
3372 CCommon::DeleteModelessDialog(search_box_ctrl);
3373 }
3374
InitSearchBoxControl(CWnd * pWnd)3375 void UiElement::SearchBox::InitSearchBoxControl(CWnd* pWnd)
3376 {
3377 CCommon::DeleteModelessDialog(search_box_ctrl);
3378 search_box_ctrl = new CUiSearchBox(pWnd);
3379 search_box_ctrl->Create();
3380 }
3381
OnKeyWordsChanged()3382 void UiElement::SearchBox::OnKeyWordsChanged()
3383 {
3384 FindListElement();
3385 if (list_element != nullptr)
3386 list_element->QuickSearch(key_word);
3387 }
3388
Clear()3389 void UiElement::SearchBox::Clear()
3390 {
3391 search_box_ctrl->Clear();
3392 }
3393
Draw()3394 void UiElement::SearchBox::Draw()
3395 {
3396 CalculateRect();
3397 ui->DrawSearchBox(rect, this);
3398 Element::Draw();
3399 }
3400
MouseMove(CPoint point)3401 void UiElement::SearchBox::MouseMove(CPoint point)
3402 {
3403 hover = false;
3404 clear_btn.hover = false;
3405 //鼠标指向图标区域
3406 if (icon_rect.PtInRect(point))
3407 {
3408 clear_btn.hover = true;
3409 //更新鼠标提示
3410 if (!key_word.empty())
3411 ui->UpdateMouseToolTipPosition(TooltipIndex::SEARCHBOX_CLEAR_BTN, clear_btn.rect);
3412 else
3413 ui->UpdateMouseToolTipPosition(TooltipIndex::SEARCHBOX_CLEAR_BTN, CRect());
3414 }
3415 //指向搜索框区域
3416 else if (rect.PtInRect(point))
3417 {
3418 hover = true;
3419 }
3420 }
3421
MouseLeave()3422 void UiElement::SearchBox::MouseLeave()
3423 {
3424 hover = false;
3425 clear_btn.hover = false;
3426 }
3427
LButtonUp(CPoint point)3428 void UiElement::SearchBox::LButtonUp(CPoint point)
3429 {
3430 clear_btn.pressed = false;
3431 //点击清除按钮时清除搜索结果
3432 if (icon_rect.PtInRect(point))
3433 {
3434 search_box_ctrl->Clear();
3435 }
3436 //点击搜索框区域时显示搜索框控件
3437 else if (search_box_ctrl != nullptr && rect.PtInRect(point))
3438 {
3439 bool big_font{ ui->m_ui_data.full_screen && ui->IsDrawLargeIcon() };
3440 search_box_ctrl->Show(this, big_font);
3441 }
3442 }
3443
LButtonDown(CPoint point)3444 void UiElement::SearchBox::LButtonDown(CPoint point)
3445 {
3446 if (icon_rect.PtInRect(point))
3447 {
3448 clear_btn.pressed = true;
3449 }
3450 }
3451
FindListElement()3452 void UiElement::SearchBox::FindListElement()
3453 {
3454 if (!find_list_element)
3455 {
3456 list_element = FindRelatedElement<ListElement>(this);
3457 if (list_element != nullptr)
3458 list_element->SetRelatedSearchBox(this);
3459 find_list_element = true; //找过一次没找到就不找了
3460 }
3461 }
3462
3463 ////////////////////////////////////////////////////////////////////////////////////////
3464 ////////////////////////////////////////////////////////////////////////////////////////
CreateElement(const std::string & name,CPlayerUIBase * ui)3465 std::shared_ptr<UiElement::Element> CElementFactory::CreateElement(const std::string& name, CPlayerUIBase* ui)
3466 {
3467 std::shared_ptr<UiElement::Element> element;
3468 if (name == "verticalLayout")
3469 {
3470 auto layout = std::make_shared<UiElement::Layout>();
3471 layout->type = UiElement::Layout::Vertical;
3472 element = layout;
3473 }
3474 else if (name == "horizontalLayout")
3475 {
3476 auto layout = std::make_shared<UiElement::Layout>();
3477 layout->type = UiElement::Layout::Horizontal;
3478 element = layout;
3479 }
3480 else if (name == "stackElement")
3481 element = std::make_shared<UiElement::StackElement>();
3482 else if (name == "rectangle")
3483 element = std::make_shared<UiElement::Rectangle>();
3484 else if (name == "button")
3485 element = std::make_shared<UiElement::Button>();
3486 else if (name == "text")
3487 element = std::make_shared<UiElement::Text>();
3488 else if (name == "albumCover")
3489 element = std::make_shared<UiElement::AlbumCover>();
3490 else if (name == "spectrum")
3491 element = std::make_shared<UiElement::Spectrum>();
3492 else if (name == "trackInfo")
3493 element = std::make_shared<UiElement::TrackInfo>();
3494 else if (name == "toolbar")
3495 element = std::make_shared<UiElement::Toolbar>();
3496 else if (name == "progressBar")
3497 element = std::make_shared<UiElement::ProgressBar>();
3498 else if (name == "lyrics")
3499 element = std::make_shared<UiElement::Lyrics>();
3500 else if (name == "volume")
3501 element = std::make_shared<UiElement::Volume>();
3502 else if (name == "beatIndicator")
3503 element = std::make_shared<UiElement::BeatIndicator>();
3504 else if (name == "playlist")
3505 element = std::make_shared<UiElement::Playlist>();
3506 else if (name == "playlistIndicator")
3507 element = std::make_shared<UiElement::PlaylistIndicator>();
3508 else if (name == "classicalControlBar")
3509 element = std::make_shared<UiElement::ClassicalControlBar>();
3510 else if (name == "recentPlayedList")
3511 element = std::make_shared<UiElement::RecentPlayedList>();
3512 else if (name == "mediaLibItemList")
3513 element = std::make_shared<UiElement::MediaLibItemList>();
3514 else if (name == "navigationBar")
3515 element = std::make_shared<UiElement::NavigationBar>();
3516 else if (name == "mediaLibFolder")
3517 element = std::make_shared<UiElement::MediaLibFolder>();
3518 else if (name == "mediaLibPlaylist")
3519 element = std::make_shared<UiElement::MediaLibPlaylist>();
3520 else if (name == "myFavouriteList")
3521 element = std::make_shared<UiElement::MyFavouriteList>();
3522 else if (name == "allTracksList")
3523 element = std::make_shared<UiElement::AllTracksList>();
3524 else if (name == "miniSpectrum")
3525 element = std::make_shared<UiElement::MiniSpectrum>();
3526 else if (name == "placeHolder")
3527 element = std::make_shared<UiElement::PlaceHolder>();
3528 else if (name == "medialibFolderExplore")
3529 element = std::make_shared<UiElement::FolderExploreTree>();
3530 else if (name == "searchBox")
3531 element = std::make_shared<UiElement::SearchBox>();
3532 else if (name == "ui" || name == "root" || name == "element")
3533 element = std::make_shared<UiElement::Element>();
3534
3535 if (element != nullptr)
3536 element->SetUi(ui);
3537 return element;
3538 }
3539