OSDN Git Service

An attempt to reduce build time
[winmerge-jp/winmerge-jp.git] / Src / DirColsDlg.cpp
1 /** 
2  * @file  DirColsDlg.cpp
3  *
4  * @brief Implementation file for CDirColsDlg
5  *
6  * @date  Created: 2003-08-19
7  */
8
9
10 #include "stdafx.h"
11 #include "DirColsDlg.h"
12 #include <algorithm>
13
14 #ifdef _DEBUG
15 #define new DEBUG_NEW
16 #endif
17
18 /////////////////////////////////////////////////////////////////////////////
19 // CDirColsDlg dialog
20
21 /**
22  * @brief Default dialog constructor.
23  * @param [in] pParent Dialog's parent component (window).
24  */
25 CDirColsDlg::CDirColsDlg(CWnd* pParent /*= nullptr*/)
26         : CTrDialog(CDirColsDlg::IDD, pParent)
27         , m_bReset(false)
28         , m_showAdditionalProperties(false)
29 {
30 }
31
32 /**
33  * @brief Handle dialog data exchange between controls and variables.
34  */
35 void CDirColsDlg::DoDataExchange(CDataExchange* pDX)
36 {
37         CTrDialog::DoDataExchange(pDX);
38         //{{AFX_DATA_MAP(CDirColsDlg)
39         DDX_Control(pDX, IDC_COLDLG_LIST, m_listColumns);
40         //}}AFX_DATA_MAP
41 }
42
43 BEGIN_MESSAGE_MAP(CDirColsDlg, CTrDialog)
44         //{{AFX_MSG_MAP(CDirColsDlg)
45         ON_BN_CLICKED(IDC_UP, OnUp)
46         ON_BN_CLICKED(IDC_DOWN, OnDown)
47         ON_BN_CLICKED(IDC_COLDLG_ADDITIONAL_PROPERTIES, OnAdditionalProperties)
48         ON_BN_CLICKED(IDC_COLDLG_DEFAULTS, OnDefaults)
49         //}}AFX_MSG_MAP
50         ON_NOTIFY(LVN_ITEMCHANGED, IDC_COLDLG_LIST, OnLvnItemchangedColdlgList)
51 END_MESSAGE_MAP()
52
53 /////////////////////////////////////////////////////////////////////////////
54 // CDirColsDlg message handlers
55
56 /**
57  * @brief Initialize listcontrol in dialog.
58  */
59 void CDirColsDlg::InitList()
60 {
61         const int lpx = CClientDC(this).GetDeviceCaps(LOGPIXELSX);
62         auto pointToPixel = [lpx](int point) { return MulDiv(point, lpx, 72); };
63
64         // Show selection across entire row.
65         // Also enable infotips.
66         m_listColumns.SetExtendedStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
67         m_listColumns.InsertColumn(0, _T(""), LVCFMT_LEFT, pointToPixel(148));
68 }
69
70 /**
71  * @brief Dialog initialisation. Load column lists.
72  */
73 BOOL CDirColsDlg::OnInitDialog() 
74 {
75         CTrDialog::OnInitDialog();
76         InitList();
77         LoadLists();
78 #ifndef _WIN64
79         EnableDlgItem(IDC_COLDLG_ADDITIONAL_PROPERTIES, false);
80 #endif
81         
82         return TRUE;  // return TRUE unless you set the focus to a control
83                       // EXCEPTION: OCX Property Pages should return FALSE
84 }
85
86 /**
87  * @brief Load listboxes on screen from column array.
88  */
89 void CDirColsDlg::LoadLists()
90 {
91         for (ColumnArray::iterator iter = m_cols.begin(); iter != m_cols.end(); ++iter)
92         {
93                 const column & c = *iter;
94                 int x = m_listColumns.InsertItem(m_listColumns.GetItemCount(),
95                         c.name.c_str());
96                 m_listColumns.SetItemData(x, c.log_col);
97                 if (c.phy_col >= 0)
98                         m_listColumns.SetCheck(x, TRUE);
99         }
100         SortArrayToLogicalOrder();
101         
102         // Set first item to selected state
103         SelectItem(0);
104 }
105
106 /**
107  * @brief Select item in list.
108  * @param [in] index Index of item to select.
109  */
110 void CDirColsDlg::SelectItem(int index)
111 {
112         m_listColumns.SetItemState(index, LVIS_SELECTED, LVIS_SELECTED);
113 }
114
115 /**
116  * @brief Load listboxes on screen from defaults column array
117  */
118 void CDirColsDlg::LoadDefLists()
119 {
120         for (ColumnArray::iterator iter = m_defCols.begin(); iter != m_defCols.end(); ++iter)
121         {
122                 const column & c = *iter;
123                 int x = m_listColumns.InsertItem(m_listColumns.GetItemCount(),
124                         c.name.c_str());
125                 m_listColumns.SetItemData(x, c.log_col);
126                 if (c.phy_col >= 0)
127                         m_listColumns.SetCheck(x, TRUE);
128         }
129         SortArrayToLogicalOrder();
130 }
131 /**
132  * @brief Sort m_cols so that it is in logical column order.
133  */
134 void CDirColsDlg::SortArrayToLogicalOrder()
135 {
136         std::sort(m_cols.begin(), m_cols.end(), &CompareColumnsByLogicalOrder);
137 }
138
139 /**
140  * @brief Compare column order of two columns.
141  * @param [in] el1 First column to compare.
142  * @param [in] el2 Second column to compare.
143  * @return Column order.
144  */
145 bool CDirColsDlg::CompareColumnsByLogicalOrder( const column & el1, const column & el2 )
146 {
147    return el1.log_col < el2.log_col;
148 }
149
150 /**
151  * @brief Move column name in the list.
152  * @param [in] index Index of column to move.
153  * @param [in] newIndex New index for the column to move.
154  */
155 void CDirColsDlg::MoveItem(int index, int newIndex)
156 {
157         // Get current column data
158         String text =  m_listColumns.GetItemText(index, 0);
159         bool checked = !!m_listColumns.GetCheck(index);
160         UINT state = m_listColumns.GetItemState(index, LVIS_SELECTED);
161         DWORD_PTR data = m_listColumns.GetItemData(index);
162
163         // Delete column
164         m_listColumns.DeleteItem(index);
165         
166         // Insert column in new index
167         m_listColumns.InsertItem(newIndex, text.c_str());
168         m_listColumns.SetItemState(newIndex, state, LVIS_SELECTED);
169         m_listColumns.SetItemData(newIndex, data);
170         if (checked)
171                 m_listColumns.SetCheck(newIndex);
172 }
173
174 /**
175  * @brief Move selected items one position up or down.
176  * @param [in] bUp If `true` items are moved up,
177  *  if `false` items are moved down.
178  */
179 void CDirColsDlg::MoveSelectedItems(bool bUp)
180 {
181         int firstInd = -1;
182         POSITION pos = m_listColumns.GetFirstSelectedItemPosition();
183
184         while (pos != nullptr)
185         {
186                 int ind = m_listColumns.GetNextSelectedItem(pos);
187                 int newInd = bUp ? ind - 1: ind + 1;
188                 
189                 // Remember first item
190                 if (firstInd == -1)
191                         firstInd = newInd;
192                 MoveItem(ind, newInd);
193         }
194         m_listColumns.EnsureVisible(firstInd, FALSE);
195 }
196
197 /**
198  * @brief Move selected items up in list.
199  */
200 void CDirColsDlg::OnUp()
201 {
202         MoveSelectedItems(true);
203 }
204
205 /**
206  * @brief Move selected items down (in show list)
207  */
208 void CDirColsDlg::OnDown() 
209 {
210         MoveSelectedItems(false);
211 }
212
213 /**
214  * @brief Close this dialog and show Additional Properties dialog
215  */
216 void CDirColsDlg::OnAdditionalProperties() 
217 {
218         m_showAdditionalProperties = true;
219         OnOK();
220 }
221
222 /**
223  * @brief Move hidden columns as last items in the list.
224  */
225 void CDirColsDlg::SanitizeOrder()
226 {
227         // Find last visible column.
228         int i = m_listColumns.GetItemCount() - 1;
229         for ( ; i >= 0; i--)
230         {
231                 if (m_listColumns.GetCheck(i))
232                         break;
233         }
234
235         // Move all hidden columns below last visible column.
236         for (int j = i; j >= 0; j--)
237         {
238                 if (!m_listColumns.GetCheck(j))
239                 {
240                         MoveItem(j, i);
241                         i--;
242                 }
243         }
244 }
245
246 /**
247  * @brief User clicked ok, so we update m_cols and close.
248  */
249 void CDirColsDlg::OnOK() 
250 {
251         SanitizeOrder();
252
253         size_t colssize = m_cols.size();
254         for (int i = 0; i < m_listColumns.GetItemCount(); i++)
255         {
256                 bool checked = !!m_listColumns.GetCheck(i);
257                 DWORD_PTR data = m_listColumns.GetItemData(i);
258                 assert(data < colssize);
259                 if (data < colssize)
260                 {
261                         column& col1 = m_cols[data];
262                         if (checked)
263                                 col1.phy_col = i;
264                         else
265                                 col1.phy_col = -1;
266                 }
267         }
268
269         CTrDialog::OnOK();
270 }
271
272 /**
273  * @brief Empty lists and load default columns and order.
274  */
275 void CDirColsDlg::OnDefaults()
276 {
277         m_listColumns.DeleteAllItems();
278         m_bReset = true;
279         LoadDefLists();
280 }
281
282 /**
283  * @brief Update description when selected item changes.
284  */
285 void CDirColsDlg::OnLvnItemchangedColdlgList(NMHDR *pNMHDR, LRESULT *pResult)
286 {
287         POSITION pos = m_listColumns.GetFirstSelectedItemPosition();
288
289         if (pos != nullptr)
290         {
291                 int ind = m_listColumns.GetNextSelectedItem(pos);
292                 DWORD_PTR data = m_listColumns.GetItemData(ind);
293
294                 ColumnArray::size_type j;
295                 for (j = 0; j < m_cols.size(); j++)
296                 {
297                         if (static_cast<DWORD_PTR>(m_cols[j].log_col) == data)
298                                 break;
299                 }
300                 SetDlgItemText(IDC_COLDLG_DESC, m_cols[j].desc);
301
302                 // Disable Up/Down -buttons when first/last items are selected.
303                 EnableDlgItem(IDC_UP, ind != 0);
304                 EnableDlgItem(IDC_DOWN,
305                         ind != m_listColumns.GetItemCount() - static_cast<int>(m_listColumns.GetSelectedCount()));
306         }
307
308         // Disable the "OK" button when no items are checked.
309         bool bChecked = false;
310         for (int i = 0; i < m_listColumns.GetItemCount(); i++)
311                 if (!!m_listColumns.GetCheck(i))
312                 {
313                         bChecked = true;
314                         break;
315                 }
316         EnableDlgItem(IDOK, bChecked);
317
318         *pResult = 0;
319 }