2 * @file PreferencesDlg.cpp
4 * @brief Implementation file for CPreferencesDlg
6 * @note This code originates from AbstractSpoon / TodoList
7 * (http://www.abstractspoon.com/) but is modified to use in
12 #include "PreferencesDlg.h"
14 #include "UnicodeString.h"
15 #include "OptionsDef.h"
16 #include "OptionsMgr.h"
17 #include "SyntaxColors.h"
20 #include "FileOrFolderSelect.h"
21 #include "OptionsSyntaxColors.h"
28 * @brief Location for file compare specific help to open.
30 static TCHAR OptionsHelpLocation[] = _T("::/htmlhelp/Configuration.html");
32 /////////////////////////////////////////////////////////////////////////////
33 // CPreferencesDlg dialog
35 const TCHAR PATHDELIM = '>';
37 CPreferencesDlg::CPreferencesDlg(COptionsMgr *regOptions, SyntaxColors *colors,
38 UINT nMenuID /*= 0*/, CWnd* pParent /*= nullptr*/) // standard constructor
39 : CTrDialog(IDD_PREFERENCES, pParent)
40 , m_pOptionsMgr(regOptions)
41 , m_pSyntaxColors(colors)
42 , m_pageGeneral(regOptions)
43 , m_pageCompare(regOptions)
44 , m_pageMessageBoxes(regOptions)
45 , m_pageColorSchemes(regOptions)
46 , m_pageMergeColors(regOptions)
47 , m_pageTextColors(regOptions, colors)
48 , m_pageSyntaxColors(regOptions, colors)
49 , m_pageMarkerColors(regOptions, colors)
50 , m_pageDirColors(regOptions)
51 , m_pageArchive(regOptions)
52 , m_pageCodepage(regOptions)
53 , m_pageEditor(regOptions)
54 , m_pageEditorSyntax(regOptions)
55 , m_pageSystem(regOptions)
56 , m_pageBackups(regOptions)
57 , m_pageShell(regOptions)
58 , m_pageCompareFolder(regOptions)
59 , m_pageCompareTable(regOptions)
60 , m_pageCompareBinary(regOptions)
61 , m_pageCompareImage(regOptions)
63 UNREFERENCED_PARAMETER(nMenuID);
66 CPreferencesDlg::~CPreferencesDlg()
70 void CPreferencesDlg::DoDataExchange(CDataExchange* pDX)
72 CDialog::DoDataExchange(pDX);
73 //{{AFX_DATA_MAP(CPreferencesDlg)
74 DDX_Control(pDX, IDC_TREEOPT_PAGES, m_tcPages);
78 BEGIN_MESSAGE_MAP(CPreferencesDlg, CTrDialog)
79 //{{AFX_MSG_MAP(CPreferencesDlg)
81 ON_COMMAND(ID_HELP, OnHelpButton)
82 ON_BN_CLICKED(IDC_TREEOPT_HELP, OnHelpButton)
83 ON_NOTIFY(TVN_SELCHANGED, IDC_TREEOPT_PAGES, OnSelchangedPages)
84 ON_BN_CLICKED(IDC_TREEOPT_IMPORT, OnImportButton)
85 ON_BN_CLICKED(IDC_TREEOPT_EXPORT, OnExportButton)
86 ON_MESSAGE(WM_APP + IDC_COLOR_SCHEMES, OnColorSchemeChanged)
90 /////////////////////////////////////////////////////////////////////////////
91 // CPreferencesDlg message handlers
93 BOOL CPreferencesDlg::OnInitDialog()
95 CTrDialog::OnInitDialog();
97 m_tcPages.SetIndent(0);
99 // Second parameter is 'path', page's parent page(s) and caption.
100 // '>' is used as path separator.
101 // For example "General" creates top-level "General" page
102 // and "General>Colors" creates "Colors" sub-page for "General"
103 AddPage(&m_pageGeneral, IDS_OPTIONSPG_GENERAL);
104 AddPage(&m_pageCompare, IDS_OPTIONSPG_COMPARE, IDS_OPTIONSPG_GENCOMPARE);
105 AddPage(&m_pageCompareFolder, IDS_OPTIONSPG_COMPARE, IDS_OPTIONSPG_FOLDERCOMPARE);
106 AddPage(&m_pageCompareTable, IDS_OPTIONSPG_COMPARE, IDS_OPTIONSPG_TABLECOMPARE);
107 AddPage(&m_pageCompareBinary, IDS_OPTIONSPG_COMPARE, IDS_OPTIONSPG_BINARYCOMPARE);
108 AddPage(&m_pageCompareImage, IDS_OPTIONSPG_COMPARE, IDS_OPTIONSPG_IMAGECOMPARE);
109 AddPage(&m_pageMessageBoxes, IDS_OPTIONSPG_MESSAGEBOXES);
110 AddPage(&m_pageEditor, IDS_OPTIONSPG_EDITOR, IDS_OPTIONSPG_GENEDITOR);
111 AddPage(&m_pageEditorSyntax, IDS_OPTIONSPG_EDITOR, IDS_OPTIONSPG_EDITOR_SYNTAX);
112 AddPage(&m_pageColorSchemes, IDS_OPTIONSPG_COLORS, IDS_OPTIONSPG_COLOR_SCHEMES);
113 AddPage(&m_pageMergeColors, IDS_OPTIONSPG_COLORS, IDS_OPTIONSPG_MERGECOLORS);
114 AddPage(&m_pageSyntaxColors, IDS_OPTIONSPG_COLORS, IDS_OPTIONSPG_SYNTAXCOLORS);
115 AddPage(&m_pageTextColors, IDS_OPTIONSPG_COLORS, IDS_OPTIONSPG_TEXTCOLORS);
116 AddPage(&m_pageMarkerColors, IDS_OPTIONSPG_COLORS, IDS_OPTIONSPG_MARKERCOLORS);
117 AddPage(&m_pageDirColors, IDS_OPTIONSPG_COLORS, IDS_OPTIONSPG_DIRCOLORS);
118 AddPage(&m_pageArchive, IDS_OPTIONSPG_ARCHIVE);
119 AddPage(&m_pageSystem, IDS_OPTIONSPG_SYSTEM);
120 AddPage(&m_pageBackups, IDS_OPTIONSPG_BACKUPS);
121 AddPage(&m_pageCodepage, IDS_OPTIONSPG_CODEPAGE);
122 AddPage(&m_pageShell, IDS_OPTIONSPG_SHELL);
127 GetDlgItem(IDC_TREEOPT_HOSTFRAME)->GetWindowRect(rPPHost);
128 ScreenToClient(rPPHost);
130 if (m_pphost.Create(rPPHost, this))
131 SetActivePage(AfxGetApp()->GetProfileInt(_T("Settings"), _T("OptStartPage"), 0));
133 // setup handler for resizing this dialog
134 m_constraint.InitializeCurrentSize(this);
135 m_constraint.DisallowHeightGrowth();
136 m_constraint.SubclassWnd(); // install subclassing
137 m_constraint.LoadPosition(_T("ResizeableDialogs"), _T("OptionsDlg"), false); // persist size via registry
138 return TRUE; // return TRUE unless you set the focus to a control
139 // EXCEPTION: OCX Property Pages should return FALSE
142 void CPreferencesDlg::OnOK()
149 AfxGetApp()->WriteProfileInt(_T("Settings"), _T("OptStartPage"), m_pphost.GetActiveIndex());
152 void CPreferencesDlg::OnSize(UINT nType, int cx, int cy)
154 CWnd::OnSize(nType, cx, cy);
156 if (CWnd *pPPHostWnd = GetDlgItem(IDC_TREEOPT_HOSTFRAME))
159 pPPHostWnd->GetWindowRect(rPPHost);
160 ScreenToClient(rPPHost);
161 m_pphost.MoveWindow(&rPPHost);
165 void CPreferencesDlg::OnHelpButton()
167 theApp.ShowHelp(OptionsHelpLocation);
170 void CPreferencesDlg::AddPage(CPropertyPage* pPage, UINT nResourceID)
172 String sPath = theApp.LoadString(nResourceID);
173 AddPage(pPage, sPath.c_str());
176 void CPreferencesDlg::AddPage(CPropertyPage* pPage, UINT nTopHeading, UINT nSubHeading)
178 String sPath = theApp.LoadString(nTopHeading);
180 sPath += theApp.LoadString(nSubHeading);
181 AddPage(pPage, sPath.c_str());
184 void CPreferencesDlg::AddPage(CPropertyPage* pPage, LPCTSTR szPath)
186 CString sPath(szPath);
188 if (m_pphost.AddPage(pPage))
190 HTREEITEM htiParent = TVI_ROOT; // default
191 int nFind = sPath.Find(PATHDELIM);
195 CString sParent = sPath.Left(nFind);
196 sPath = sPath.Mid(nFind + 1);
198 // see if parent already exists
199 HTREEITEM htiParentParent = htiParent;
200 htiParent = m_tcPages.GetChildItem(htiParentParent);
202 while (htiParent != nullptr)
204 if (sParent.CompareNoCase(m_tcPages.GetItemText(htiParent)) == 0)
207 htiParent = m_tcPages.GetNextItem(htiParent, TVGN_NEXT);
210 if (htiParent == nullptr)
211 htiParent = m_tcPages.InsertItem(sParent, htiParentParent);
213 nFind = sPath.Find(PATHDELIM);
216 HTREEITEM hti = m_tcPages.InsertItem(sPath, htiParent); // whatever's left
217 m_tcPages.EnsureVisible(hti);
220 m_tcPages.SetItemData(hti, static_cast<DWORD_PTR>(reinterpret_cast<uintptr_t>(pPage)));
221 m_mapPP2HTI[(void*)pPage] = (void*)hti;
225 void CPreferencesDlg::OnSelchangedPages(NMHDR* pNMHDR, LRESULT* pResult)
227 UNREFERENCED_PARAMETER(pNMHDR);
228 HTREEITEM htiSel = m_tcPages.GetSelectedItem();
230 while (m_tcPages.ItemHasChildren(htiSel))
231 htiSel = m_tcPages.GetChildItem(htiSel);
233 CPropertyPage* pPage = (CPropertyPage*)m_tcPages.GetItemData(htiSel);
234 ASSERT (pPage != nullptr);
236 if (pPage != nullptr)
238 m_pphost.SetActivePage(pPage, false);
241 String sCaption = strutils::format_string1(_("Options (%1)"), (LPCTSTR)GetItemPath(htiSel));
242 SetWindowText(sCaption.c_str());
245 m_tcPages.SetFocus();
250 void CPreferencesDlg::SetActivePage(int nPage)
252 m_pphost.SetActivePage(nPage, false);
255 CPropertyPage* pPage = m_pphost.GetActivePage();
256 HTREEITEM hti = nullptr;
258 if (m_mapPP2HTI.Lookup(pPage, (void*&)hti) && hti != nullptr)
259 m_tcPages.SelectItem(hti);
262 CString CPreferencesDlg::GetItemPath(HTREEITEM hti)
264 CString sPath = m_tcPages.GetItemText(hti);
266 hti = m_tcPages.GetParentItem(hti);
267 while (hti != nullptr)
269 sPath = m_tcPages.GetItemText(hti) + _T(" > ") + sPath;
270 hti = m_tcPages.GetParentItem(hti);
277 * @brief Read options from storage to UI controls.
278 * @param [in] bUpdate If `true` UpdateData() is called
280 void CPreferencesDlg::ReadOptions(bool bUpdate)
282 m_pageGeneral.ReadOptions();
283 m_pageColorSchemes.ReadOptions();
284 m_pageMergeColors.ReadOptions();
285 m_pageTextColors.ReadOptions();
286 m_pageSyntaxColors.ReadOptions();
287 m_pageMarkerColors.ReadOptions();
288 m_pageDirColors.ReadOptions();
289 m_pageSystem.ReadOptions();
290 m_pageCompare.ReadOptions();
291 m_pageCompareFolder.ReadOptions();
292 m_pageCompareTable.ReadOptions();
293 m_pageCompareBinary.ReadOptions();
294 m_pageCompareImage.ReadOptions();
295 m_pageMessageBoxes.ReadOptions();
296 m_pageEditor.ReadOptions();
297 m_pageEditorSyntax.ReadOptions();
298 m_pageCodepage.ReadOptions();
299 m_pageArchive.ReadOptions();
300 m_pageBackups.ReadOptions();
301 m_pageShell.ReadOptions();
305 SafeUpdatePage(&m_pageGeneral, false);
306 SafeUpdatePage(&m_pageColorSchemes, false);
307 SafeUpdatePage(&m_pageMergeColors, false);
308 SafeUpdatePage(&m_pageTextColors, false);
309 SafeUpdatePage(&m_pageSyntaxColors, false);
310 SafeUpdatePage(&m_pageMarkerColors, false);
311 SafeUpdatePage(&m_pageDirColors, false);
312 SafeUpdatePage(&m_pageSystem, false);
313 SafeUpdatePage(&m_pageCompare, false);
314 SafeUpdatePage(&m_pageCompareFolder, false);
315 SafeUpdatePage(&m_pageCompareTable, false);
316 SafeUpdatePage(&m_pageCompareBinary, false);
317 SafeUpdatePage(&m_pageCompareImage, false);
318 SafeUpdatePage(&m_pageMessageBoxes, false);
319 SafeUpdatePage(&m_pageEditor, false);
320 SafeUpdatePage(&m_pageEditorSyntax, false);
321 SafeUpdatePage(&m_pageCodepage, false);
322 SafeUpdatePage(&m_pageArchive, false);
323 SafeUpdatePage(&m_pageBackups, false);
324 SafeUpdatePage(&m_pageShell, false);
329 * @brief Write options from UI to storage.
331 void CPreferencesDlg::SaveOptions()
333 m_pageGeneral.WriteOptions();
334 m_pageSystem.WriteOptions();
335 m_pageCompare.WriteOptions();
336 m_pageCompareFolder.WriteOptions();
337 m_pageCompareTable.WriteOptions();
338 m_pageCompareBinary.WriteOptions();
339 m_pageCompareImage.WriteOptions();
340 m_pageMessageBoxes.WriteOptions();
341 m_pageEditor.WriteOptions();
342 m_pageEditorSyntax.WriteOptions();
343 m_pageColorSchemes.WriteOptions();
344 m_pageMergeColors.WriteOptions();
345 m_pageTextColors.WriteOptions();
346 m_pageSyntaxColors.WriteOptions();
347 m_pageMarkerColors.WriteOptions();
348 m_pageDirColors.WriteOptions();
349 m_pageCodepage.WriteOptions();
350 m_pageArchive.WriteOptions();
351 m_pageBackups.WriteOptions();
352 m_pageShell.WriteOptions();
356 * @brief Imports options from file.
358 void CPreferencesDlg::OnImportButton()
361 if (SelectFile(GetSafeHwnd(), s, true, nullptr, _("Select file for import"), _("Options files (*.ini)|*.ini|All Files (*.*)|*.*||")))
363 if (m_pOptionsMgr->ImportOptions(s) == COption::OPT_OK)
365 Options::SyntaxColors::Load(m_pOptionsMgr, m_pSyntaxColors);
367 LangMessageBox(IDS_OPT_IMPORT_DONE, MB_ICONINFORMATION);
370 LangMessageBox(IDS_OPT_IMPORT_ERR, MB_ICONWARNING);
375 * @brief Exports options to file.
377 void CPreferencesDlg::OnExportButton()
380 if (SelectFile(GetSafeHwnd(), settingsFile, false, nullptr, _("Select file for export"),
381 _("Options files (*.ini)|*.ini|All Files (*.*)|*.*||")))
383 // Add settings file extension if it is missing
384 // So we allow 'filename.otherext' but add extension for 'filename'
385 if (paths::FindExtension(settingsFile).empty())
386 settingsFile += _T(".ini");
388 // Save all new settings before exporting
389 m_pphost.UpdatePagesData();
392 if (m_pOptionsMgr->ExportOptions(settingsFile, true) == COption::OPT_OK)
393 LangMessageBox(IDS_OPT_EXPORT_DONE, MB_ICONINFORMATION);
395 LangMessageBox(IDS_OPT_EXPORT_ERR, MB_ICONWARNING);
399 LRESULT CPreferencesDlg::OnColorSchemeChanged(WPARAM wParams, LPARAM lParam)
401 Options::SyntaxColors::Load(m_pOptionsMgr, m_pSyntaxColors);
407 * @brief Do a safe UpdateData call for propertypage.
408 * This function does safe UpdateData call for given propertypage. As it is,
409 * all propertypages may not have been yet initialized properly, so we must
410 * have some care when calling updateData for them.
411 * @param [in] pPage Propertypage to update.
412 * @param bSaveAndValidate UpdateData direction parameter.
414 void CPreferencesDlg::SafeUpdatePage(CPropertyPage* pPage, bool bSaveAndValidate)
416 if (pPage->GetSafeHwnd() != nullptr)
417 pPage->UpdateData(bSaveAndValidate);