1 ////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // Nestopia - NES/Famicom emulator written in C++
4 //
5 // Copyright (C) 2003-2008 Martin Freij
6 //
7 // This file is part of Nestopia.
8 //
9 // Nestopia is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Nestopia is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Nestopia; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 ////////////////////////////////////////////////////////////////////////////////////////
24 
25 #include "NstResourceString.hpp"
26 #include "NstWindowParam.hpp"
27 #include "NstDialogLauncher.hpp"
28 
29 namespace Nestopia
30 {
31 	namespace Window
32 	{
33 		NST_COMPILE_ASSERT
34 		(
35 			IDS_LAUNCHER_COLUMN_SYSTEM    == IDS_LAUNCHER_COLUMN_FILE +  1 &&
36 			IDS_LAUNCHER_COLUMN_MAPPER    == IDS_LAUNCHER_COLUMN_FILE +  2 &&
37 			IDS_LAUNCHER_COLUMN_PRG       == IDS_LAUNCHER_COLUMN_FILE +  3 &&
38 			IDS_LAUNCHER_COLUMN_CHR       == IDS_LAUNCHER_COLUMN_FILE +  4 &&
39 			IDS_LAUNCHER_COLUMN_WRAM      == IDS_LAUNCHER_COLUMN_FILE +  5 &&
40 			IDS_LAUNCHER_COLUMN_VRAM      == IDS_LAUNCHER_COLUMN_FILE +  6 &&
41 			IDS_LAUNCHER_COLUMN_BATTERY   == IDS_LAUNCHER_COLUMN_FILE +  7 &&
42 			IDS_LAUNCHER_COLUMN_DUMP      == IDS_LAUNCHER_COLUMN_FILE +  8 &&
43 			IDS_LAUNCHER_COLUMN_NAME      == IDS_LAUNCHER_COLUMN_FILE +  9 &&
44 			IDS_LAUNCHER_COLUMN_FOLDER    == IDS_LAUNCHER_COLUMN_FILE + 10
45 		);
46 
47 		wcstring const Launcher::List::Columns::cfgStrings[NUM_TYPES] =
48 		{
49 			L"file",
50 			L"system",
51 			L"mapper",
52 			L"prg",
53 			L"chr",
54 			L"wram",
55 			L"vram",
56 			L"battery",
57 			L"dump",
58 			L"name",
59 			L"folder"
60 		};
61 
62 		struct Launcher::List::Columns::Handlers
63 		{
64 			static const MsgHandler::Entry<Columns> messages[];
65 			static const MsgHandler::Entry<Columns> commands[];
66 		};
67 
68 		const MsgHandler::Entry<Launcher::List::Columns> Launcher::List::Columns::Handlers::messages[] =
69 		{
70 			{ WM_INITDIALOG, &Columns::OnInitDialog }
71 		};
72 
73 		const MsgHandler::Entry<Launcher::List::Columns> Launcher::List::Columns::Handlers::commands[] =
74 		{
75 			{ IDC_LAUNCHER_COLUMNSELECT_SELECTED,  &Columns::OnCmdSelected  },
76 			{ IDC_LAUNCHER_COLUMNSELECT_AVAILABLE, &Columns::OnCmdAvailable },
77 			{ IDC_LAUNCHER_COLUMNSELECT_ADD,       &Columns::OnCmdAdd       },
78 			{ IDC_LAUNCHER_COLUMNSELECT_REMOVE,    &Columns::OnCmdRemove    },
79 			{ IDC_LAUNCHER_COLUMNSELECT_DEFAULT,   &Columns::OnCmdDefault   },
80 			{ IDOK,                                &Columns::OnCmdOk        }
81 		};
82 
Columns(const Configuration & cfg)83 		Launcher::List::Columns::Columns(const Configuration& cfg)
84 		:
85 		available (NUM_TYPES),
86 		dialog    (IDD_LAUNCHER_COLUMNS,this,Handlers::messages,Handlers::commands)
87 		{
88 			Configuration::ConstSection column( cfg["launcher"]["view"]["columns"]["column"] );
89 
90 			for (uint i=0; i < NUM_TYPES; ++i)
91 				available[i] = i;
92 
93 			selected.Reserve( NUM_TYPES );
94 
95 			for (uint i=0; i < NUM_TYPES; ++i)
96 			{
97 				const GenericString string( column[i].Str() );
98 
99 				if (string.Empty())
100 					break;
101 
102 				for (Types::Iterator it(available.Begin()), end(available.End()); it != end; ++it)
103 				{
104 					if (string == cfgStrings[*it])
105 					{
106 						selected.PushBack( *it );
107 						available.Erase( it );
108 						break;
109 					}
110 				}
111 			}
112 
113 			if (selected.Empty())
114 				Reset();
115 		}
116 
Reset()117 		void Launcher::List::Columns::Reset()
118 		{
119 			selected.Resize( NUM_DEFAULT_SELECTED_TYPES );
120 			available.Resize( NUM_DEFAULT_AVAILABLE_TYPES );
121 
122 			for (uint i=0; i < NUM_DEFAULT_SELECTED_TYPES; ++i)
123 				selected[i] = i;
124 
125 			for (uint i=0; i < NUM_DEFAULT_AVAILABLE_TYPES; ++i)
126 				available[i] = NUM_DEFAULT_SELECTED_TYPES + i;
127 		}
128 
Update(const uchar * const order)129 		void Launcher::List::Columns::Update(const uchar* const order)
130 		{
131 			selected.Assign( order, selected.Size() );
132 		}
133 
Save(Configuration & cfg) const134 		void Launcher::List::Columns::Save(Configuration& cfg) const
135 		{
136 			if (const uint n=selected.Size())
137 			{
138 				Configuration::Section column( cfg["launcher"]["view"]["columns"]["column"] );
139 
140 				for (uint i=0; i < n; ++i)
141 					column[i].Str() = cfgStrings[selected[i]];
142 			}
143 		}
144 
UpdateButtonRemove()145 		void Launcher::List::Columns::UpdateButtonRemove()
146 		{
147 			const Control::ListBox list( dialog.ListBox(IDC_LAUNCHER_COLUMNSELECT_SELECTED) );
148 
149 			dialog.Control(IDC_LAUNCHER_COLUMNSELECT_REMOVE).Enable
150 			(
151 				list.Size() > 1 && list.Selection()
152 			);
153 		}
154 
UpdateButtonAdd()155 		void Launcher::List::Columns::UpdateButtonAdd()
156 		{
157 			dialog.Control(IDC_LAUNCHER_COLUMNSELECT_ADD).Enable
158 			(
159 				dialog.ListBox(IDC_LAUNCHER_COLUMNSELECT_AVAILABLE).Selection()
160 			);
161 		}
162 
OnInitDialog(Param &)163 		ibool Launcher::List::Columns::OnInitDialog(Param&)
164 		{
165 			Control::ListBox list( dialog.ListBox(IDC_LAUNCHER_COLUMNSELECT_SELECTED) );
166 			list.Reserve( selected.Size() );
167 
168 			for (Types::ConstIterator it(selected.Begin()), end(selected.End()); it != end; ++it)
169 				list.Add( Resource::String( IDS_LAUNCHER_COLUMN_FILE + *it ) );
170 
171 			list[0].Select();
172 			list = dialog.ListBox(IDC_LAUNCHER_COLUMNSELECT_AVAILABLE);
173 			list.Reserve( available.Size() );
174 
175 			for (Types::ConstIterator it(available.Begin()), end(available.End()); it != end; ++it)
176 				list.Add( Resource::String( IDS_LAUNCHER_COLUMN_FILE + *it ) );
177 
178 			list[0].Select();
179 			return true;
180 		}
181 
OnCmdSelected(Param & param)182 		ibool Launcher::List::Columns::OnCmdSelected(Param& param)
183 		{
184 			if (param.ListBox().SelectionChanged())
185 				UpdateButtonRemove();
186 
187 			return true;
188 		}
189 
OnCmdAvailable(Param & param)190 		ibool Launcher::List::Columns::OnCmdAvailable(Param& param)
191 		{
192 			if (param.ListBox().SelectionChanged())
193 				UpdateButtonAdd();
194 
195 			return true;
196 		}
197 
OnCmdAdd(Param & param)198 		ibool Launcher::List::Columns::OnCmdAdd(Param& param)
199 		{
200 			if (param.Button().Clicked())
201 				Add( IDC_LAUNCHER_COLUMNSELECT_SELECTED, IDC_LAUNCHER_COLUMNSELECT_AVAILABLE );
202 
203 			return true;
204 		}
205 
OnCmdRemove(Param & param)206 		ibool Launcher::List::Columns::OnCmdRemove(Param& param)
207 		{
208 			if (param.Button().Clicked())
209 				Add( IDC_LAUNCHER_COLUMNSELECT_AVAILABLE, IDC_LAUNCHER_COLUMNSELECT_SELECTED );
210 
211 			return true;
212 		}
213 
OnCmdDefault(Param & param)214 		ibool Launcher::List::Columns::OnCmdDefault(Param& param)
215 		{
216 			if (param.Button().Clicked())
217 			{
218 				Control::ListBox list( dialog.ListBox(IDC_LAUNCHER_COLUMNSELECT_SELECTED) );
219 
220 				list.Clear();
221 
222 				for (uint i=0; i < NUM_DEFAULT_SELECTED_TYPES; ++i)
223 					list.Add( Resource::String( IDS_LAUNCHER_COLUMN_FILE + i) );
224 
225 				list[0].Select();
226 
227 				list = dialog.ListBox(IDC_LAUNCHER_COLUMNSELECT_AVAILABLE);
228 				list.Clear();
229 
230 				for (uint i=0; i < NUM_DEFAULT_AVAILABLE_TYPES; ++i)
231 					list.Add( Resource::String( IDS_LAUNCHER_COLUMN_FILE + NUM_DEFAULT_SELECTED_TYPES + i) );
232 
233 				list[0].Select();
234 
235 				dialog.Control( IDC_LAUNCHER_COLUMNSELECT_REMOVE ).Enable();
236 				dialog.Control( IDC_LAUNCHER_COLUMNSELECT_ADD    ).Enable();
237 			}
238 
239 			return true;
240 		}
241 
OnCmdOk(Param & param)242 		ibool Launcher::List::Columns::OnCmdOk(Param& param)
243 		{
244 			if (param.Button().Clicked())
245 			{
246 				HeapString text;
247 
248 				for (uint i=0; i < 2; ++i)
249 				{
250 					Control::ListBox list = dialog.ListBox
251 					(
252 						i ? IDC_LAUNCHER_COLUMNSELECT_SELECTED :
253 							IDC_LAUNCHER_COLUMNSELECT_AVAILABLE
254 					);
255 
256 					Types& types = (i ? selected : available);
257 					types.Resize( list.Size() );
258 
259 					for (uint j=0; j < types.Size(); ++j)
260 					{
261 						list[j].Text() >> text;
262 
263 						for (uint k=0; k < NUM_TYPES; ++k)
264 						{
265 							if (text == Resource::String( IDS_LAUNCHER_COLUMN_FILE + k))
266 							{
267 								types[j] = k;
268 								break;
269 							}
270 						}
271 					}
272 				}
273 
274 				dialog.Close();
275 			}
276 
277 			return true;
278 		}
279 
Add(const uint iDst,const uint iSrc)280 		void Launcher::List::Columns::Add(const uint iDst,const uint iSrc)
281 		{
282 			const Control::ListBox cSrc( dialog.ListBox(iSrc) );
283 			const int sSrc = cSrc.Selection().GetIndex();
284 
285 			if (sSrc >= 0 && (iDst == IDC_LAUNCHER_COLUMNSELECT_SELECTED || cSrc.Size() > 1))
286 			{
287 				HeapString text;
288 				cSrc[sSrc].Text() >> text;
289 
290 				const Control::ListBox cDst( dialog.ListBox(iDst) );
291 				const int sDst = cDst.Selection().GetIndex();
292 
293 				if (sDst >= 0)
294 					cDst.Insert( sDst + 1, text.Ptr() ).Select();
295 				else
296 					cDst.Add( text.Ptr() );
297 
298 				cSrc[sSrc].Remove();
299 
300 				if (cSrc.Size() > sSrc)
301 					cSrc[sSrc].Select();
302 
303 				UpdateButtonRemove();
304 				UpdateButtonAdd();
305 			}
306 		}
307 	}
308 }
309