Skip to content

Commit

Permalink
实现ui中树控件的搜索功能
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongyang219 committed Aug 30, 2024
1 parent 100586c commit 335c661
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 38 deletions.
118 changes: 83 additions & 35 deletions MusicPlayer2/UIElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2936,16 +2936,31 @@ std::wstring UiElement::TreeElement::GetItemText(int row, int col)

int UiElement::TreeElement::GetRowCount()
{
const auto& root_nodes{ GetRootNodes() };
int row_count{};
IterateDisplayedNodeInOrder([&](const Node*) ->bool {
row_count++;
return false;
});
return row_count;
}

void UiElement::TreeElement::QuickSearch(const std::wstring& key_word)
{
tree_searched = !key_word.empty();

tree_search_result.clear();
if (key_word.empty())
return;
//遍历所有节点,获取匹配的节点,并添加到tree_search_result中
const auto& root_nodes{ GetRootNodes() };
for (const auto& root : root_nodes)
{
root->IterateNodeInOrder([&](const Node*) ->bool {
row_count++;
root->IterateNodeInOrder([&](const Node* cur_node) ->bool {
if (IsNodeMathcKeyWord(cur_node, key_word))
tree_search_result.insert(cur_node);
return false;
}, true);
}, false);
}
return row_count;
}

int UiElement::TreeElement::GetItemLevel(int row)
Expand Down Expand Up @@ -3024,23 +3039,17 @@ void UiElement::TreeElement::MouseLeave()

int UiElement::TreeElement::GetNodeIndex(const Node* node)
{
const auto& root_nodes{ GetRootNodes() };
int i{};
int rtn_index{ -1 };
for (const auto& root : root_nodes)
{
root->IterateNodeInOrder([&](const Node* cur_node) ->bool {
if (cur_node == node)
{
rtn_index = i;
return true;
}
i++;
return false;
}, true);
if (rtn_index >= 0)
break;
}
IterateDisplayedNodeInOrder([&](const Node* cur_node) ->bool {
if (cur_node == node)
{
rtn_index = i;
return true;
}
i++;
return false;
});

return rtn_index;
}
Expand All @@ -3050,28 +3059,67 @@ UiElement::TreeElement::Node* UiElement::TreeElement::GetNodeByIndex(int index)
if (index >= 0)
{
Node* find_node{};
auto& root_nodes{ GetRootNodes() };
int i{};
for (auto& root : root_nodes)
{
root->IterateNodeInOrder([&](Node* cur_node) ->bool {
if (i == index)
{
find_node = cur_node;
return true;
}
i++;
return false;
}, true);
if (find_node != nullptr)
break;
}
IterateDisplayedNodeInOrder([&](Node* cur_node) ->bool {
if (i == index)
{
find_node = cur_node;
return true;
}
i++;
return false;
});
return find_node;
}

return nullptr;
}

bool UiElement::TreeElement::IsNodeMathcKeyWord(const Node* node, const std::wstring& key_word)
{
//判断节点本身是否匹配
for (const auto& item : node->texts)
{
const std::wstring& text{ item.second };
if (!text.empty() && theApp.m_chinese_pingyin_res.IsStringMatchWithPingyin(key_word, text))
return true;
}

//如果节点本身不匹配,则遍历所有子节点,如果有一个子节点匹配,则节点匹配
for (const auto& child : node->child_list)
{
if (IsNodeMathcKeyWord(child.get(), key_word))
return true;
}

return false;
}

bool UiElement::TreeElement::IsNodeDisplayed(const Node* node)
{
if (node != nullptr)
{
if (tree_searched)
return tree_search_result.contains(node);
else
return true;
}
return false;
}

void UiElement::TreeElement::IterateDisplayedNodeInOrder(std::function<bool(Node*)> func)
{
const auto& root_nodes{ GetRootNodes() };
for (const auto& root : root_nodes)
{
root->IterateNodeInOrder([&](Node* cur_node) ->bool {
if (IsNodeDisplayed(cur_node))
return func(cur_node);
return false;
}, true);
}
}

UiElement::TestTree::TestTree()
{
//创建测试节点
Expand Down
14 changes: 11 additions & 3 deletions MusicPlayer2/UIElement.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include "CPlayerUIBase.h"
#include "MediaLibHelper.h"
#include <set>

class CUiSearchBox;

Expand Down Expand Up @@ -329,7 +330,7 @@ namespace UiElement
virtual bool IsMultipleSelectionEnable() { return false; } //是否允许多选
virtual void OnRowCountChanged(); //当列表行数发生变化时响应此函数

void QuickSearch(const std::wstring& key_word); //根据关键执行快速搜索(筛选出匹配的项)
virtual void QuickSearch(const std::wstring& key_word); //根据关键执行快速搜索(筛选出匹配的项)
virtual bool IsItemMatchKeyWord(int row, const std::wstring& key_word); //判断指定行是否匹配关键字(用于快速搜索功能,默认匹配每一列中的文本,只要有一列的文本匹配就返回true,派生类可重写此函数)

int GetDisplayRowCount(); //获取要显示的行数。(处于搜索状态时返回搜索结果数量,正常状态下同GetRowCount)
Expand Down Expand Up @@ -363,6 +364,7 @@ namespace UiElement
int scroll_handle_length_comp{}; //计算滚动条把手长度时的补偿量
std::map<int, IPlayerUI::UIButton> hover_buttons; //鼠标指向时的按钮
int last_row_count{};
private:
std::vector<int> search_result; //保存搜索结果的序号
bool searched{}; //是否处于搜索状态
};
Expand Down Expand Up @@ -758,14 +760,20 @@ namespace UiElement
// 通过 ListElement 继承
std::wstring GetItemText(int row, int col) override;
int GetRowCount() override;
//树控件不使用基类ListElement的搜索逻辑
virtual void QuickSearch(const std::wstring& key_word) override;

std::map<int, CRect> collapsd_rects; //折叠标志的矩形区域(key是行)
int collaps_indicator_hover_row{ -1 }; //鼠标指向的折叠标志的行号

protected:
int GetNodeIndex(const Node* node); //查找一个节点的序号(如果节点被折叠或不存在则返回-1)
Node* GetNodeByIndex(int index); //根据一个节点的序号查找节点(忽略被折叠的节点)

Node* GetNodeByIndex(int index); //根据一个节点的序号查找节点(忽略被折叠的节点)
bool IsNodeMathcKeyWord(const Node* node, const std::wstring& key_word); //判断一个节点是否匹配关键字
bool IsNodeDisplayed(const Node* node);
void IterateDisplayedNodeInOrder(std::function<bool(Node*)> func); //遍历所有可见的节点
std::set<const Node*> tree_search_result; //保存搜索结果
bool tree_searched{}; //是否处于搜索状态
};

class TestTree : public TreeElement
Expand Down

0 comments on commit 335c661

Please sign in to comment.