OSDN Git Service

refactor
[winmerge-jp/winmerge-jp.git] / Src / DirAdditionalPropertiesDlg.cpp
1 /** 
2  * @file  DirAdditionalPropertiesDlg.cpp
3  *
4  * @brief Implementation file for CDirAdditionalPropertiesDlg
5  */
6
7 #include "stdafx.h"
8 #include "DirAdditionalPropertiesDlg.h"
9 #include "PropertySystem.h"
10 #include "unicoder.h"
11 #include <algorithm>
12
13 #ifdef _DEBUG
14 #define new DEBUG_NEW
15 #endif
16
17 /////////////////////////////////////////////////////////////////////////////
18 // CDirAdditionalPropertiesDlg dialog
19
20 /**
21  * @brief Default dialog constructor.
22  * @param [in] pParent Dialog's parent component (window).
23  */
24 CDirAdditionalPropertiesDlg::CDirAdditionalPropertiesDlg(const std::vector<String>& canonicalNames, CWnd* pParent /*= nullptr*/)
25         : CTrDialog(CDirAdditionalPropertiesDlg::IDD, pParent)
26         , m_canonicalNames(canonicalNames)
27         , m_root{}
28 {
29 }
30
31 /**
32  * @brief Handle dialog data exchange between controls and variables.
33  */
34 void CDirAdditionalPropertiesDlg::DoDataExchange(CDataExchange* pDX)
35 {
36         CTrDialog::DoDataExchange(pDX);
37         //{{AFX_DATA_MAP(CDirAdditionalPropertiesDlg)
38         DDX_Control(pDX, IDC_PROPS_TREEVIEW, m_treeProps);
39         DDX_Control(pDX, IDC_PROPS_LISTVIEW, m_listProps);
40         //}}AFX_DATA_MAP
41 }
42
43 BEGIN_MESSAGE_MAP(CDirAdditionalPropertiesDlg, CTrDialog)
44         //{{AFX_MSG_MAP(CDirAdditionalPropertiesDlg)
45         ON_BN_CLICKED(IDC_PROPS_ADD, OnAdd)
46         ON_COMMAND_RANGE(IDC_PROPS_DEL, IDC_PROPS_DELALL, OnDelete)
47         ON_NOTIFY(NM_DBLCLK, IDC_PROPS_TREEVIEW, OnDblClkTreeView)
48         ON_NOTIFY(TVN_KEYDOWN, IDC_PROPS_TREEVIEW, OnKeyDownTreeView)
49         ON_NOTIFY(LVN_KEYDOWN, IDC_PROPS_LISTVIEW, OnKeyDownListView)
50         //}}AFX_MSG_MAP
51 END_MESSAGE_MAP()
52
53 Node& CDirAdditionalPropertiesDlg::MakeNode(Node& parentNode, const std::vector<StringView>& path, std::vector<StringView>::iterator it)
54 {
55         for (auto& node : parentNode.childNodes)
56         {
57                 if (node.name == *it)
58                 {
59                         ++it;
60                         if (it != path.end())
61                                 return MakeNode(node, path, it);
62                         return node;
63                 }
64         }
65         Node& node = parentNode.childNodes.emplace_back();
66         node.selected = false;
67         node.name = *it;
68         ++it;
69         if (it != path.end())
70         {
71                 node.hItem = m_treeProps.InsertItem(tr(ucr::toUTF8(node.name)).c_str(), parentNode.hItem);
72                 return MakeNode(node, path, it);
73         }
74         node.canonicalName = strutils::join(path.begin(), path.end(), _T("."));
75         PropertySystem ps({ node.canonicalName });
76         std::vector<String> displayNames;
77         ps.GetDisplayNames(displayNames);
78         node.displayName = displayNames[0];
79         node.hItem = m_treeProps.InsertItem(node.displayName.c_str(), parentNode.hItem);
80         m_treeProps.SetItemData(node.hItem, reinterpret_cast<DWORD_PTR>(&node));
81         return node;
82 }
83
84 void CDirAdditionalPropertiesDlg::LoadList()
85 {
86         m_root.hItem = TVI_ROOT;
87         PropertySystem ps(PropertySystem::VIEWABLE);
88         for (const auto& canonicalName : ps.GetCanonicalNames())
89         {
90                 PropertySystem ps2({ canonicalName });
91                 std::vector<String> displayNames;
92                 ps2.GetDisplayNames(displayNames);
93                 if (!displayNames[0].empty())
94                 {
95                         auto path = strutils::split(canonicalName, '.');
96                         Node& node = MakeNode(m_root, path, path.begin());
97                         if (std::count(m_canonicalNames.begin(), m_canonicalNames.end(), canonicalName) > 0)
98                         {
99                                 for (HTREEITEM hItem = m_treeProps.GetParentItem(node.hItem); hItem; hItem = m_treeProps.GetParentItem(hItem))
100                                         m_treeProps.Expand(hItem, TVE_EXPAND);
101                                 node.selected = true;
102                                 m_treeProps.SetItemState(node.hItem, TVIS_BOLD, TVIS_BOLD);
103                                 m_listProps.InsertItem(LVIF_TEXT|LVIF_PARAM,
104                                         m_listProps.GetItemCount(), node.displayName.c_str(),
105                                         0, 0, 0, reinterpret_cast<LPARAM>(&node));
106                         }
107                 }
108         }
109         if (!m_root.childNodes.empty())
110                 m_treeProps.SelectItem(m_root.childNodes.front().hItem);
111 }
112
113 /////////////////////////////////////////////////////////////////////////////
114 // CDirAdditionalPropertiesDlg message handlers
115
116 BOOL CDirAdditionalPropertiesDlg::OnInitDialog()
117 {
118         CTrDialog::OnInitDialog();
119
120         CRect rc;
121         m_listProps.GetClientRect(&rc);
122         m_listProps.InsertColumn(0, _T(""), LVCFMT_LEFT, rc.Width());
123         LoadList();
124
125         return TRUE;  // return TRUE unless you set the focus to a control
126                       // EXCEPTION: OCX Property Pages should return FALSE
127 }
128
129 void CDirAdditionalPropertiesDlg::OnAdd() 
130 {
131         HTREEITEM hItem = m_treeProps.GetSelectedItem();
132         if (hItem)
133         {
134                 Node* pNode = reinterpret_cast<Node*>(m_treeProps.GetItemData(hItem));
135                 if (pNode && !pNode->selected)
136                 {
137                         pNode->selected = true;
138                         m_treeProps.SetItemState(pNode->hItem, TVIS_BOLD, TVIS_BOLD);
139                         m_listProps.InsertItem(LVIF_TEXT|LVIF_PARAM,
140                                 m_listProps.GetItemCount(), pNode->displayName.c_str(),
141                                 0, 0, 0, reinterpret_cast<LPARAM>(pNode));
142                 }
143         }
144 }
145
146 void CDirAdditionalPropertiesDlg::OnDelete(UINT nId) 
147 {
148         for (int i = m_listProps.GetItemCount() - 1; i >= 0; --i)
149         {
150                 if (nId == IDC_PROPS_DELALL || m_listProps.GetItemState(i, LVIS_SELECTED) != 0)
151                 {
152                         Node* pNode = reinterpret_cast<Node*>(m_listProps.GetItemData(i));
153                         if (pNode)
154                         {
155                                 pNode->selected = false;
156                                 m_treeProps.SetItemState(pNode->hItem, 0, TVIS_BOLD);
157                                 m_listProps.DeleteItem(i);
158                         }
159                 }
160         }
161 }
162
163 void CDirAdditionalPropertiesDlg::OnDblClkTreeView(NMHDR* pNMHDR, LRESULT* pResult)
164 {
165         HTREEITEM hItem = m_treeProps.GetSelectedItem();
166         if (hItem)
167         {
168                 Node* pNode = reinterpret_cast<Node*>(m_treeProps.GetItemData(hItem));
169                 if (pNode)
170                 {
171                         if (pNode->selected)
172                         {
173                                 for (int i = 0; i < m_listProps.GetItemCount(); ++i)
174                                 {
175                                         bool selected = (pNode == reinterpret_cast<Node*>(m_listProps.GetItemData(i)));
176                                         m_listProps.SetItemState(i, selected ? LVIS_SELECTED : 0, LVIS_SELECTED);
177                                 }
178                                 OnDelete(IDC_PROPS_DEL);
179                         }
180                         else
181                         {
182                                 OnAdd();
183                         }
184                 }
185         }
186         *pResult = 0;
187 }
188
189 void CDirAdditionalPropertiesDlg::OnKeyDownTreeView(NMHDR* pNMHDR, LRESULT* pResult)
190 {
191         NMTVKEYDOWN* pNMKEY = reinterpret_cast<NMTVKEYDOWN*>(pNMHDR);
192         if (pNMKEY->wVKey == VK_SPACE)
193         {
194                 OnDblClkTreeView(pNMHDR, pResult);
195                 *pResult = 1;
196         }
197         else
198         {
199                 *pResult = 0;
200         }
201 }
202
203 void CDirAdditionalPropertiesDlg::OnKeyDownListView(NMHDR* pNMHDR, LRESULT* pResult)
204 {
205         NMLVKEYDOWN* pNMKEY = reinterpret_cast<NMLVKEYDOWN*>(pNMHDR);
206         if (pNMKEY->wVKey == VK_DELETE)
207         {
208                 OnDelete(IDC_PROPS_DEL);
209                 *pResult = 1;
210         }
211         else
212         {
213                 *pResult = 0;
214         }
215 }
216
217 void CDirAdditionalPropertiesDlg::OnOK() 
218 {
219         CTrDialog::OnOK();
220         m_canonicalNames.clear();
221         for (int i = 0; i < m_listProps.GetItemCount(); ++i)
222         {
223                 Node* pNode = reinterpret_cast<Node*>(m_listProps.GetItemData(i));
224                 if (pNode)
225                         m_canonicalNames.push_back(pNode->canonicalName);
226         }
227 }
228