aboutsummaryrefslogtreecommitdiff
path: root/Src/external_dependencies/openmpt-trunk/mptrack/GeneralConfigDlg.cpp
blob: b1cb79a034e4231a2ffc7e13c028ae45746cf19d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
/*
 * GeneralConfigDlg.cpp
 * --------------------
 * Purpose: Implementation of the general settings dialog.
 * Notes  : (currently none)
 * Authors: OpenMPT Devs
 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 */


#include "stdafx.h"
#include "Mainfrm.h"
#include "GeneralConfigDlg.h"
#include "Settings.h"
#include "FileDialog.h"
#include "../common/mptStringBuffer.h"
#include "FolderScanner.h"


OPENMPT_NAMESPACE_BEGIN

BEGIN_MESSAGE_MAP(COptionsGeneral, CPropertyPage)
	ON_LBN_SELCHANGE(IDC_LIST1,		&COptionsGeneral::OnOptionSelChanged)
	ON_CLBN_CHKCHANGE(IDC_LIST1,	&COptionsGeneral::OnSettingsChanged)
	ON_COMMAND(IDC_RADIO1,			&COptionsGeneral::OnSettingsChanged)
	ON_COMMAND(IDC_RADIO2,			&COptionsGeneral::OnSettingsChanged)
	ON_COMMAND(IDC_RADIO3,			&COptionsGeneral::OnSettingsChanged)
	ON_EN_CHANGE(IDC_EDIT1,			&COptionsGeneral::OnSettingsChanged)
	ON_CBN_SELCHANGE(IDC_COMBO1,	&COptionsGeneral::OnDefaultTypeChanged)
	ON_CBN_SELCHANGE(IDC_COMBO2,	&COptionsGeneral::OnTemplateChanged)
	ON_CBN_EDITCHANGE(IDC_COMBO2,	&COptionsGeneral::OnTemplateChanged)
	ON_COMMAND(IDC_BUTTON1,			&COptionsGeneral::OnBrowseTemplate)
END_MESSAGE_MAP()


static constexpr struct GeneralOptionsDescriptions
{
	uint32 flag;
	const char *name, *description;
} generalOptionsList[] =
{
	{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)."},
	{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."},
	{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."},
	{PATTERN_PLAYTRANSPOSE,	"Play notes when transposing",		"When transposing a single note, the new note is previewed."},
	{PATTERN_CENTERROW,		"Always center active row",			"Turn on this option to have the active row always centered in the pattern editor."},
	{PATTERN_SMOOTHSCROLL,	"Smooth pattern scrolling",			"Scroll patterns tick by tick rather than row by row at the expense of an increased CPU load."},
	{PATTERN_HEXDISPLAY,	"Display rows in hex",				"With this option enabled, row numbers and sequence numbers will be displayed in hexadecimal."},
	{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."},
	{PATTERN_DRAGNDROPEDIT,	"Drag and Drop Editing",			"Enable moving a selection in the pattern editor (copying if pressing shift while dragging)"},
	{PATTERN_FLATBUTTONS,	"Flat Buttons",						"Use flat buttons in toolbars"},
	{PATTERN_SINGLEEXPAND,	"Single click to expand tree",		"Single-clicking in the left tree view will expand a node."},
	{PATTERN_MUTECHNMODE,	"Ignored muted channels",			"Notes will not be played on muted channels (unmuting will only start on a new note)."},
	{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)."},
	{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."},
	{PATTERN_CONTSCROLL,	"Continuous scroll",				"Jumps to the next pattern when moving past the end of a pattern"},
	{PATTERN_KBDNOTEOFF,	"Record note off",					"Record note off when a key is released on the PC keyboard."},
	{PATTERN_FOLLOWSONGOFF,	"Follow Song off by default",		"Ensure Follow Song is off when opening or starting a new song."},
	{PATTERN_NOFOLLOWONCLICK,"Disable Follow Song on click",	"Follow Song is deactivated when clicking into the pattern."},
	{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."},
	{PATTERN_SYNCMUTE,		"Maintain sample sync on mute",		"Samples continue to be processed when channels are muted (like in IT2 and FT2)"},
	{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."},
	{PATTERN_AUTODELAY,		"Automatic delay commands",			"Automatically insert appropriate note-delay commands when recording notes during live playback."},
	{PATTERN_NOTEFADE,		"Note fade on key up",				"Enable to fade / stop notes on key up in pattern tab."},
	{PATTERN_OVERFLOWPASTE,	"Overflow paste mode",				"Wrap pasted pattern data into next pattern. This is useful for creating echo channels."},
	{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."},
	{PATTERN_LIVEUPDATETREE,"Update sample status in tree",		"If enabled, active samples and instruments will be indicated by a different icon in the treeview."},
	{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."},
	{PATTERN_DBLCLICKSELECT, "Double-click to select channel",	"Instead of showing the note properties, double-clicking a pattern cell selects the whole channel."},
	{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."},
};


void COptionsGeneral::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CModTypeDlg)
	DDX_Control(pDX, IDC_LIST1,		m_CheckList);
	DDX_Control(pDX, IDC_EDIT1,		m_defaultArtist);
	DDX_Control(pDX, IDC_COMBO2,	m_defaultTemplate);
	DDX_Control(pDX, IDC_COMBO1,	m_defaultFormat);
	//}}AFX_DATA_MAP
}


BOOL COptionsGeneral::OnInitDialog()
{
	CPropertyPage::OnInitDialog();

	m_defaultArtist.SetWindowText(mpt::ToCString(TrackerSettings::Instance().defaultArtist));

	const struct
	{
		MODTYPE type;
		const TCHAR *str;
	} formats[] =
	{
		{ MOD_TYPE_MOD, _T("MOD") },
		{ MOD_TYPE_XM, _T("XM") },
		{ MOD_TYPE_S3M, _T("S3M") },
		{ MOD_TYPE_IT, _T("IT") },
		{ MOD_TYPE_MPT, _T("MPTM") },
	};
	m_defaultFormat.SetCurSel(0);
	for(const auto &fmt : formats)
	{
		auto idx = m_defaultFormat.AddString(fmt.str);
		m_defaultFormat.SetItemData(idx, fmt.type);
		if(fmt.type == TrackerSettings::Instance().defaultModType)
		{
			m_defaultFormat.SetCurSel(idx);
		}
	}

	const mpt::PathString basePath = theApp.GetConfigPath() + P_("TemplateModules\\");
	FolderScanner scanner(basePath, FolderScanner::kOnlyFiles | FolderScanner::kFindInSubDirectories);
	mpt::PathString file;
	while(scanner.Next(file))
	{
		mpt::RawPathString fileW = file.AsNative();
		fileW = fileW.substr(basePath.Length());
		::SendMessage(m_defaultTemplate.m_hWnd, CB_ADDSTRING, 0, (LPARAM)fileW.c_str());
	}
	file = TrackerSettings::Instance().defaultTemplateFile;
	if(file.GetPath() == basePath)
	{
		file = file.GetFullFileName();
	}
	m_defaultTemplate.SetWindowText(file.AsNative().c_str());

	CheckRadioButton(IDC_RADIO1, IDC_RADIO3, IDC_RADIO1 + TrackerSettings::Instance().defaultNewFileAction);

	for(const auto &opt : generalOptionsList)
	{
		auto idx = m_CheckList.AddString(mpt::ToCString(mpt::Charset::ASCII, opt.name));
		const int check = (TrackerSettings::Instance().m_dwPatternSetup & opt.flag) != 0 ? BST_CHECKED : BST_UNCHECKED;
		m_CheckList.SetCheck(idx, check);
	}
	m_CheckList.SetCurSel(0);
	OnOptionSelChanged();

	return TRUE;
}


void COptionsGeneral::OnOK()
{
	TrackerSettings::Instance().defaultArtist = GetWindowTextUnicode(m_defaultArtist);
	TrackerSettings::Instance().defaultModType = static_cast<MODTYPE>(m_defaultFormat.GetItemData(m_defaultFormat.GetCurSel()));
	TrackerSettings::Instance().defaultTemplateFile = mpt::PathString::FromCString(GetWindowTextString(m_defaultTemplate));

	NewFileAction action = nfDefaultFormat;
	int newActionRadio = GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO3);
	if(newActionRadio == IDC_RADIO2) action = nfSameAsCurrent;
	if(newActionRadio == IDC_RADIO3) action = nfDefaultTemplate;
	if(action == nfDefaultTemplate && TrackerSettings::Instance().defaultTemplateFile.Get().empty())
	{
		action = nfDefaultFormat;
		::MessageBeep(MB_ICONWARNING);
	}
	TrackerSettings::Instance().defaultNewFileAction = action;

	for(int i = 0; i < mpt::saturate_cast<int>(std::size(generalOptionsList)); i++)
	{
		const bool check = (m_CheckList.GetCheck(i) != BST_UNCHECKED);

		if(check) TrackerSettings::Instance().m_dwPatternSetup |= generalOptionsList[i].flag;
		else TrackerSettings::Instance().m_dwPatternSetup &= ~generalOptionsList[i].flag;
	}

	CMainFrame::GetMainFrame()->SetupMiscOptions();

	CPropertyPage::OnOK();
}


BOOL COptionsGeneral::OnSetActive()
{
	CMainFrame::m_nLastOptionsPage = OPTIONS_PAGE_GENERAL;
	return CPropertyPage::OnSetActive();
}


void COptionsGeneral::OnOptionSelChanged()
{
	const char *desc = "";
	const int sel = m_CheckList.GetCurSel();
	if ((sel >= 0) && (sel < mpt::saturate_cast<int>(std::size(generalOptionsList))))
	{
		desc = generalOptionsList[sel].description;
	}
	SetDlgItemText(IDC_TEXT1, mpt::ToCString(mpt::Charset::ASCII, desc));
}


void COptionsGeneral::OnBrowseTemplate()
{
	mpt::PathString basePath = theApp.GetInstallPath() + P_("TemplateModules\\");
	mpt::PathString defaultFile = mpt::PathString::FromCString(GetWindowTextString(m_defaultTemplate));
	if(defaultFile.empty()) defaultFile = TrackerSettings::Instance().defaultTemplateFile;

	OpenFileDialog dlg;
	if(defaultFile.empty())
	{
		dlg.WorkingDirectory(basePath);
	} else
	{
		if(defaultFile.AsNative().find_first_of(_T("/\\")) == mpt::RawPathString::npos)
		{
			// Relative path
			defaultFile = basePath + defaultFile;
		}
		dlg.DefaultFilename(defaultFile);
	}
	if(dlg.Show(this))
	{
		defaultFile = dlg.GetFirstFile();
		if(defaultFile.GetPath() == basePath)
		{
			defaultFile = defaultFile.GetFullFileName();
		}
		m_defaultTemplate.SetWindowText(defaultFile.AsNative().c_str());
		OnTemplateChanged();
	}
}

OPENMPT_NAMESPACE_END