GeneralConfigDlg.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * GeneralConfigDlg.cpp
  3. * --------------------
  4. * Purpose: Implementation of the general settings dialog.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #include "stdafx.h"
  10. #include "Mainfrm.h"
  11. #include "GeneralConfigDlg.h"
  12. #include "Settings.h"
  13. #include "FileDialog.h"
  14. #include "../common/mptStringBuffer.h"
  15. #include "FolderScanner.h"
  16. OPENMPT_NAMESPACE_BEGIN
  17. BEGIN_MESSAGE_MAP(COptionsGeneral, CPropertyPage)
  18. ON_LBN_SELCHANGE(IDC_LIST1, &COptionsGeneral::OnOptionSelChanged)
  19. ON_CLBN_CHKCHANGE(IDC_LIST1, &COptionsGeneral::OnSettingsChanged)
  20. ON_COMMAND(IDC_RADIO1, &COptionsGeneral::OnSettingsChanged)
  21. ON_COMMAND(IDC_RADIO2, &COptionsGeneral::OnSettingsChanged)
  22. ON_COMMAND(IDC_RADIO3, &COptionsGeneral::OnSettingsChanged)
  23. ON_EN_CHANGE(IDC_EDIT1, &COptionsGeneral::OnSettingsChanged)
  24. ON_CBN_SELCHANGE(IDC_COMBO1, &COptionsGeneral::OnDefaultTypeChanged)
  25. ON_CBN_SELCHANGE(IDC_COMBO2, &COptionsGeneral::OnTemplateChanged)
  26. ON_CBN_EDITCHANGE(IDC_COMBO2, &COptionsGeneral::OnTemplateChanged)
  27. ON_COMMAND(IDC_BUTTON1, &COptionsGeneral::OnBrowseTemplate)
  28. END_MESSAGE_MAP()
  29. static constexpr struct GeneralOptionsDescriptions
  30. {
  31. uint32 flag;
  32. const char *name, *description;
  33. } generalOptionsList[] =
  34. {
  35. {PATTERN_PLAYNEWNOTE, "Play new notes while recording", "When this option is enabled, notes entered in the pattern editor will always be played (If not checked, notes won't be played in record mode)."},
  36. {PATTERN_PLAYEDITROW, "Play whole row while recording", "When this option is enabled, all notes on the current row are played when entering notes in the pattern editor."},
  37. {PATTERN_PLAYNAVIGATEROW, "Play whole row when navigating", "When this option is enabled, all notes on the current row are played when navigating vertically in the pattern editor."},
  38. {PATTERN_PLAYTRANSPOSE, "Play notes when transposing", "When transposing a single note, the new note is previewed."},
  39. {PATTERN_CENTERROW, "Always center active row", "Turn on this option to have the active row always centered in the pattern editor."},
  40. {PATTERN_SMOOTHSCROLL, "Smooth pattern scrolling", "Scroll patterns tick by tick rather than row by row at the expense of an increased CPU load."},
  41. {PATTERN_HEXDISPLAY, "Display rows in hex", "With this option enabled, row numbers and sequence numbers will be displayed in hexadecimal."},
  42. {PATTERN_WRAP, "Cursor wrap in pattern editor", "When this option is active, going past the end of a pattern row or channel will move the cursor to the beginning. When \"Continuous scroll\"-option is enabled, row wrap is disabled."},
  43. {PATTERN_DRAGNDROPEDIT, "Drag and Drop Editing", "Enable moving a selection in the pattern editor (copying if pressing shift while dragging)"},
  44. {PATTERN_FLATBUTTONS, "Flat Buttons", "Use flat buttons in toolbars"},
  45. {PATTERN_SINGLEEXPAND, "Single click to expand tree", "Single-clicking in the left tree view will expand a node."},
  46. {PATTERN_MUTECHNMODE, "Ignored muted channels", "Notes will not be played on muted channels (unmuting will only start on a new note)."},
  47. {PATTERN_NOEXTRALOUD, "No loud sample preview", "Disable loud playback of samples in the sample/instrument editor. Sample volume depends on the sample volume slider on the general tab when activated (if disabled, samples are previewed at 0 dB)."},
  48. {PATTERN_SHOWPREVIOUS, "Show Prev/Next patterns", "Displays grayed-out version of the previous/next patterns in the pattern editor. Does not work if \"always center active row\" is disabled."},
  49. {PATTERN_CONTSCROLL, "Continuous scroll", "Jumps to the next pattern when moving past the end of a pattern"},
  50. {PATTERN_KBDNOTEOFF, "Record note off", "Record note off when a key is released on the PC keyboard."},
  51. {PATTERN_FOLLOWSONGOFF, "Follow Song off by default", "Ensure Follow Song is off when opening or starting a new song."},
  52. {PATTERN_NOFOLLOWONCLICK,"Disable Follow Song on click", "Follow Song is deactivated when clicking into the pattern."},
  53. {PATTERN_OLDCTXMENUSTYLE, "Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."},
  54. {PATTERN_SYNCMUTE, "Maintain sample sync on mute", "Samples continue to be processed when channels are muted (like in IT2 and FT2)"},
  55. {PATTERN_SYNCSAMPLEPOS, "Maintain sample sync on seek", "Sample that are still active from previous patterns are continued to be played after seeking.\nNote: Some pattern commands may prevent samples from being synced. This feature may slow down seeking."},
  56. {PATTERN_AUTODELAY, "Automatic delay commands", "Automatically insert appropriate note-delay commands when recording notes during live playback."},
  57. {PATTERN_NOTEFADE, "Note fade on key up", "Enable to fade / stop notes on key up in pattern tab."},
  58. {PATTERN_OVERFLOWPASTE, "Overflow paste mode", "Wrap pasted pattern data into next pattern. This is useful for creating echo channels."},
  59. {PATTERN_RESETCHANNELS, "Reset channels on loop", "If enabled, channels will be reset to their initial state when song looping is enabled.\nNote: This does not affect manual song loops (i.e. triggered by pattern commands) and is not recommended to be enabled."},
  60. {PATTERN_LIVEUPDATETREE,"Update sample status in tree", "If enabled, active samples and instruments will be indicated by a different icon in the treeview."},
  61. {PATTERN_NOCLOSEDIALOG, "Disable modern close dialog", "When closing the main window, a confirmation window is shown for every unsaved document instead of one single window with a list of unsaved documents."},
  62. {PATTERN_DBLCLICKSELECT, "Double-click to select channel", "Instead of showing the note properties, double-clicking a pattern cell selects the whole channel."},
  63. {PATTERN_SHOWDEFAULTVOLUME, "Show default volume commands", "If there is no volume command next to a note + instrument combination, the sample's default volume is shown."},
  64. };
  65. void COptionsGeneral::DoDataExchange(CDataExchange* pDX)
  66. {
  67. CDialog::DoDataExchange(pDX);
  68. //{{AFX_DATA_MAP(CModTypeDlg)
  69. DDX_Control(pDX, IDC_LIST1, m_CheckList);
  70. DDX_Control(pDX, IDC_EDIT1, m_defaultArtist);
  71. DDX_Control(pDX, IDC_COMBO2, m_defaultTemplate);
  72. DDX_Control(pDX, IDC_COMBO1, m_defaultFormat);
  73. //}}AFX_DATA_MAP
  74. }
  75. BOOL COptionsGeneral::OnInitDialog()
  76. {
  77. CPropertyPage::OnInitDialog();
  78. m_defaultArtist.SetWindowText(mpt::ToCString(TrackerSettings::Instance().defaultArtist));
  79. const struct
  80. {
  81. MODTYPE type;
  82. const TCHAR *str;
  83. } formats[] =
  84. {
  85. { MOD_TYPE_MOD, _T("MOD") },
  86. { MOD_TYPE_XM, _T("XM") },
  87. { MOD_TYPE_S3M, _T("S3M") },
  88. { MOD_TYPE_IT, _T("IT") },
  89. { MOD_TYPE_MPT, _T("MPTM") },
  90. };
  91. m_defaultFormat.SetCurSel(0);
  92. for(const auto &fmt : formats)
  93. {
  94. auto idx = m_defaultFormat.AddString(fmt.str);
  95. m_defaultFormat.SetItemData(idx, fmt.type);
  96. if(fmt.type == TrackerSettings::Instance().defaultModType)
  97. {
  98. m_defaultFormat.SetCurSel(idx);
  99. }
  100. }
  101. const mpt::PathString basePath = theApp.GetConfigPath() + P_("TemplateModules\\");
  102. FolderScanner scanner(basePath, FolderScanner::kOnlyFiles | FolderScanner::kFindInSubDirectories);
  103. mpt::PathString file;
  104. while(scanner.Next(file))
  105. {
  106. mpt::RawPathString fileW = file.AsNative();
  107. fileW = fileW.substr(basePath.Length());
  108. ::SendMessage(m_defaultTemplate.m_hWnd, CB_ADDSTRING, 0, (LPARAM)fileW.c_str());
  109. }
  110. file = TrackerSettings::Instance().defaultTemplateFile;
  111. if(file.GetPath() == basePath)
  112. {
  113. file = file.GetFullFileName();
  114. }
  115. m_defaultTemplate.SetWindowText(file.AsNative().c_str());
  116. CheckRadioButton(IDC_RADIO1, IDC_RADIO3, IDC_RADIO1 + TrackerSettings::Instance().defaultNewFileAction);
  117. for(const auto &opt : generalOptionsList)
  118. {
  119. auto idx = m_CheckList.AddString(mpt::ToCString(mpt::Charset::ASCII, opt.name));
  120. const int check = (TrackerSettings::Instance().m_dwPatternSetup & opt.flag) != 0 ? BST_CHECKED : BST_UNCHECKED;
  121. m_CheckList.SetCheck(idx, check);
  122. }
  123. m_CheckList.SetCurSel(0);
  124. OnOptionSelChanged();
  125. return TRUE;
  126. }
  127. void COptionsGeneral::OnOK()
  128. {
  129. TrackerSettings::Instance().defaultArtist = GetWindowTextUnicode(m_defaultArtist);
  130. TrackerSettings::Instance().defaultModType = static_cast<MODTYPE>(m_defaultFormat.GetItemData(m_defaultFormat.GetCurSel()));
  131. TrackerSettings::Instance().defaultTemplateFile = mpt::PathString::FromCString(GetWindowTextString(m_defaultTemplate));
  132. NewFileAction action = nfDefaultFormat;
  133. int newActionRadio = GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO3);
  134. if(newActionRadio == IDC_RADIO2) action = nfSameAsCurrent;
  135. if(newActionRadio == IDC_RADIO3) action = nfDefaultTemplate;
  136. if(action == nfDefaultTemplate && TrackerSettings::Instance().defaultTemplateFile.Get().empty())
  137. {
  138. action = nfDefaultFormat;
  139. ::MessageBeep(MB_ICONWARNING);
  140. }
  141. TrackerSettings::Instance().defaultNewFileAction = action;
  142. for(int i = 0; i < mpt::saturate_cast<int>(std::size(generalOptionsList)); i++)
  143. {
  144. const bool check = (m_CheckList.GetCheck(i) != BST_UNCHECKED);
  145. if(check) TrackerSettings::Instance().m_dwPatternSetup |= generalOptionsList[i].flag;
  146. else TrackerSettings::Instance().m_dwPatternSetup &= ~generalOptionsList[i].flag;
  147. }
  148. CMainFrame::GetMainFrame()->SetupMiscOptions();
  149. CPropertyPage::OnOK();
  150. }
  151. BOOL COptionsGeneral::OnSetActive()
  152. {
  153. CMainFrame::m_nLastOptionsPage = OPTIONS_PAGE_GENERAL;
  154. return CPropertyPage::OnSetActive();
  155. }
  156. void COptionsGeneral::OnOptionSelChanged()
  157. {
  158. const char *desc = "";
  159. const int sel = m_CheckList.GetCurSel();
  160. if ((sel >= 0) && (sel < mpt::saturate_cast<int>(std::size(generalOptionsList))))
  161. {
  162. desc = generalOptionsList[sel].description;
  163. }
  164. SetDlgItemText(IDC_TEXT1, mpt::ToCString(mpt::Charset::ASCII, desc));
  165. }
  166. void COptionsGeneral::OnBrowseTemplate()
  167. {
  168. mpt::PathString basePath = theApp.GetInstallPath() + P_("TemplateModules\\");
  169. mpt::PathString defaultFile = mpt::PathString::FromCString(GetWindowTextString(m_defaultTemplate));
  170. if(defaultFile.empty()) defaultFile = TrackerSettings::Instance().defaultTemplateFile;
  171. OpenFileDialog dlg;
  172. if(defaultFile.empty())
  173. {
  174. dlg.WorkingDirectory(basePath);
  175. } else
  176. {
  177. if(defaultFile.AsNative().find_first_of(_T("/\\")) == mpt::RawPathString::npos)
  178. {
  179. // Relative path
  180. defaultFile = basePath + defaultFile;
  181. }
  182. dlg.DefaultFilename(defaultFile);
  183. }
  184. if(dlg.Show(this))
  185. {
  186. defaultFile = dlg.GetFirstFile();
  187. if(defaultFile.GetPath() == basePath)
  188. {
  189. defaultFile = defaultFile.GetFullFileName();
  190. }
  191. m_defaultTemplate.SetWindowText(defaultFile.AsNative().c_str());
  192. OnTemplateChanged();
  193. }
  194. }
  195. OPENMPT_NAMESPACE_END