1 #include "PartsListDialog.h"
2 #include <CUI/CUIWindow.h>
3 #include <CUI/CUIDialog.h>
4 #include <CUI/CUIScaler.h>
5 #include <LDLib/LDHtmlInventory.h>
6 #include <TCFoundation/mystring.h>
7 #include "Resource.h"
8 
9 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
10 #define new DEBUG_CLIENTBLOCK
11 #endif // _DEBUG
12 
13 #ifndef ListView_SetCheckState
14    #define ListView_SetCheckState(hwndLV, i, fCheck) \
15       ListView_SetItemState(hwndLV, i, \
16       INDEXTOSTATEIMAGEMASK((fCheck)+1), LVIS_STATEIMAGEMASK)
17 #endif
18 
PartsListDialog(CUIWindow * parentWindow,LDHtmlInventory * htmlInventory)19 PartsListDialog::PartsListDialog(CUIWindow *parentWindow,
20 								 LDHtmlInventory *htmlInventory) :
21 	m_parentWindow(parentWindow),
22 	m_htmlInventory(htmlInventory),
23 	m_hDlg(NULL),
24 	m_hImageList(NULL)
25 {
26 }
27 
~PartsListDialog(void)28 PartsListDialog::~PartsListDialog(void)
29 {
30 }
31 
dealloc(void)32 void PartsListDialog::dealloc(void)
33 {
34 	if (m_hDlg)
35 	{
36 		DestroyWindow(m_hDlg);
37 		m_hDlg = NULL;
38 	}
39 	if (m_hImageList)
40 	{
41 		ImageList_Destroy(m_hImageList);
42 	}
43 	TCObject::dealloc();
44 }
45 
createDialog(void)46 void PartsListDialog::createDialog(void)
47 {
48 	if (!m_hDlg)
49 	{
50 		registerWindowClass();
51 		m_hDlg = m_parentWindow->createDialog(IDD_PARTS_LIST, TRUE,
52 			staticDialogProc, (LPARAM)this);
53 	}
54 }
55 
runModal(void)56 int PartsListDialog::runModal(void)
57 {
58 	createDialog();
59 	m_modalReturn = IDCANCEL;
60 	m_parentWindow->runDialogModal(m_hDlg);
61 	return m_modalReturn;
62 }
63 
staticDialogProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)64 INT_PTR CALLBACK PartsListDialog::staticDialogProc(HWND hDlg, UINT message,
65 												   WPARAM wParam, LPARAM lParam)
66 {
67 	PartsListDialog* dialog;
68 
69 	if (message == WM_INITDIALOG)
70 	{
71 		dialog = (PartsListDialog*)lParam;
72 		SetWindowLongPtr(hDlg, DWLP_USER, lParam);
73 	}
74 	else
75 	{
76 		dialog = (PartsListDialog*)GetWindowLongPtr(hDlg, DWLP_USER);
77 	}
78 	if (dialog)
79 	{
80 		return dialog->dialogProc(hDlg, message, wParam, lParam);
81 	}
82 	else
83 	{
84 		return FALSE;
85 	}
86 }
87 
dialogProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)88 INT_PTR PartsListDialog::dialogProc(HWND hDlg, UINT message, WPARAM wParam,
89 									LPARAM lParam)
90 {
91 	switch (message)
92 	{
93 		case WM_INITDIALOG:
94 			return doInitDialog(hDlg, (HWND)wParam, lParam);
95 			break;
96 		case WM_CLOSE:
97 			m_parentWindow->doDialogClose(hDlg);
98 			break;
99 		case WM_COMMAND:
100 			return doCommand((int)(short)LOWORD(wParam),
101 				(int)(short)HIWORD(wParam), (HWND)lParam);
102 			break;
103 		case WM_NOTIFY:
104 			return doNotify((int)(short)LOWORD(wParam), (LPNMHDR)lParam);
105 			break;
106 		default:
107 			return FALSE;
108 			//return DefDlgProc(hDlg, message, wParam, lParam);
109 			break;
110 	}
111 	return FALSE;
112 }
113 
populateColumnList(void)114 void PartsListDialog::populateColumnList(void)
115 {
116 	int i;
117 	LVCOLUMN column;
118 	DWORD exStyle = ListView_GetExtendedListViewStyle(m_hColumnList);
119 	const LDPartListColumnVector &columnOrder =
120 		m_htmlInventory->getColumnOrder();
121 	int count = 0;
122 	RECT lvClientRect;
123 	int lvWidth;
124 
125 	exStyle |= (LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
126 	ListView_SetExtendedListViewStyle(m_hColumnList, exStyle);
127 	memset(&column, 0, sizeof(LVCOLUMN));
128 	column.mask = LVCF_FMT | LVCF_WIDTH;
129 	column.fmt = LVCFMT_LEFT;
130 	column.cx = 300;
131 	ListView_InsertColumn(m_hColumnList, 0, &column);
132 	for (i = 0; i < (int)columnOrder.size(); i++)
133 	{
134 		LVITEM item;
135 		LDPartListColumn lcolumn = columnOrder[i];
136 
137 		memset(&item, 0, sizeof(item));
138 		item.mask = TVIF_TEXT | TVIF_PARAM;
139 		ucstring columnName;
140 		utf8toucstring(columnName, LDHtmlInventory::getColumnName(lcolumn));
141 		item.pszText = &columnName[0];
142 		item.lParam = lcolumn;
143 		item.iItem = count;
144 		item.iSubItem = 0;
145 		ListView_InsertItem(m_hColumnList, &item);
146 		ListView_SetCheckState(m_hColumnList, item.iItem, 1);
147 		count++;
148 	}
149 	for (i = LDPLCFirst; i <= LDPLCLast; i++)
150 	{
151 		LDPartListColumn lcolumn = (LDPartListColumn)i;
152 		if (!m_htmlInventory->isColumnEnabled(lcolumn))
153 		{
154 			LVITEM item;
155 
156 			memset(&item, 0, sizeof(item));
157 			item.mask = TVIF_TEXT | TVIF_PARAM;
158 			ucstring columnName;
159 			utf8toucstring(columnName, LDHtmlInventory::getColumnName(lcolumn));
160 			item.pszText = &columnName[0];
161 			item.lParam = i;
162 			item.iItem = count;
163 			item.iSubItem = 0;
164 			ListView_InsertItem(m_hColumnList, &item);
165 			ListView_SetCheckState(m_hColumnList, item.iItem, 0);
166 			count++;
167 		}
168 	}
169 	ListView_SetColumnWidth(m_hColumnList, 0, LVSCW_AUTOSIZE);
170 	GetClientRect(m_hColumnList, &lvClientRect);
171 	lvWidth = lvClientRect.right - lvClientRect.left;
172 	if (ListView_GetColumnWidth(m_hColumnList, 0) < lvWidth)
173 	{
174 		ListView_SetColumnWidth(m_hColumnList, 0, lvWidth);
175 	}
176 }
177 
setupToolbar(void)178 void PartsListDialog::setupToolbar(void)
179 {
180 	RECT tbRect;
181 	TBBUTTON buttons[2];
182 	char buttonTitle[128];
183 	int i;
184 
185 	int tbImageSize = m_parentWindow->scalePoints(16);
186 	int tbButtonSize = m_parentWindow->scalePoints(25);
187 	SIZE tbImageFullSize = { tbImageSize * 4, tbImageSize };
188 	UINT flags = CUIScaler::imageListCreateFlags();
189 	m_hImageList = ImageList_Create(tbImageSize, tbImageSize, flags,
190 		4, 0);
191 	m_parentWindow->addImageToImageList(m_hImageList, IDR_EXTRA_DIRS_TOOLBAR,
192 		tbImageFullSize, m_parentWindow->getScaleFactor());
193 	SendMessage(m_hToolbar, TB_SETIMAGELIST, 0, (LPARAM)m_hImageList);
194 	memset(buttonTitle, 0, sizeof(buttonTitle));
195 	GetClientRect(m_hToolbar, &tbRect);
196 	SendMessage(m_hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
197 	SendMessage(m_hToolbar, TB_SETINDENT, tbRect.right - tbRect.left -
198 		tbButtonSize * 2, 0);
199 	SendMessage(m_hToolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(tbButtonSize,
200 		tbButtonSize));
201 	SendMessage(m_hToolbar, TB_ADDSTRING, 0, (LPARAM)buttonTitle);
202 	for (i = 0; i < 2; i++)
203 	{
204 		buttons[i].iBitmap = i + 2;
205 		buttons[i].idCommand = 42 + i;
206 		buttons[i].fsState = 0;//TBSTATE_ENABLED;
207 		buttons[i].fsStyle = TBSTYLE_BUTTON;
208 		buttons[i].dwData = (DWORD_PTR)this;
209 		buttons[i].iString = -1;
210 	}
211 	SendMessage(m_hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons);
212 }
213 
updateOverwriteCheck(void)214 void PartsListDialog::updateOverwriteCheck(void)
215 {
216 	if (getCheck(IDC_SHOW_MODEL))
217 	{
218 		EnableWindow(m_hOverwrite, TRUE);
219 		setCheck(IDC_OVERWRITE, m_overwriteSnapshot);
220 	}
221 	else
222 	{
223 		EnableWindow(m_hOverwrite, FALSE);
224 		setCheck(IDC_OVERWRITE, false);
225 	}
226 }
227 
doInitDialog(HWND hDlg,HWND,LPARAM)228 INT_PTR PartsListDialog::doInitDialog(HWND hDlg, HWND /*hFocus*/,
229 									  LPARAM /*lParam*/)
230 {
231 	m_hDlg = hDlg;
232 
233 	m_hOverwrite = GetDlgItem(m_hDlg, IDC_OVERWRITE);
234 	setCheck(IDC_SHOW_MODEL, m_htmlInventory->getShowModelFlag());
235 	m_overwriteSnapshot = m_htmlInventory->getOverwriteSnapshotFlag();
236 	updateOverwriteCheck();
237 	setCheck(IDC_EXTERNAL_CSS, m_htmlInventory->getExternalCssFlag());
238 	setCheck(IDC_SHOW_PART_IMAGES, m_htmlInventory->getPartImagesFlag());
239 	setCheck(IDC_SHOW_FILE, m_htmlInventory->getShowFileFlag());
240 	m_hColumnList = GetDlgItem(m_hDlg, IDC_COLUMN_ORDER_LIST);
241 	m_hToolbar = GetDlgItem(m_hDlg, IDC_TOOLBAR);
242 	populateColumnList();
243 	setupToolbar();
244 	return TRUE;
245 }
246 
setCheck(int controlId,bool value)247 void PartsListDialog::setCheck(int controlId, bool value)
248 {
249 	CUIDialog::buttonSetChecked(m_hDlg, controlId, value);
250 }
251 
getCheck(int controlId)252 bool PartsListDialog::getCheck(int controlId)
253 {
254 	return CUIDialog::buttonIsChecked(m_hDlg, controlId);
255 }
256 
saveSettings(void)257 void PartsListDialog::saveSettings(void)
258 {
259 	int i;
260 	int count = ListView_GetItemCount(m_hColumnList);
261 	LDPartListColumnVector columnOrder;
262 
263 	if (getCheck(IDC_SHOW_MODEL))
264 	{
265 		m_htmlInventory->setShowModelFlag(true);
266 		m_overwriteSnapshot = getCheck(IDC_OVERWRITE);
267 		m_htmlInventory->setOverwriteSnapshotFlag(m_overwriteSnapshot);
268 	}
269 	else
270 	{
271 		m_htmlInventory->setShowModelFlag(false);
272 	}
273 	m_htmlInventory->setExternalCssFlag(getCheck(IDC_EXTERNAL_CSS));
274 	m_htmlInventory->setPartImagesFlag(getCheck(IDC_SHOW_PART_IMAGES));
275 	m_htmlInventory->setShowFileFlag(getCheck(IDC_SHOW_FILE));
276 	for (i = 0; i < count; i++)
277 	{
278 		if (ListView_GetCheckState(m_hColumnList, i))
279 		{
280 			LVITEM item;
281 
282 			item.mask = TVIF_PARAM;
283 			item.iItem = i;
284 			item.iSubItem = 0;
285 			if (ListView_GetItem(m_hColumnList, &item))
286 			{
287 				columnOrder.push_back((LDPartListColumn)item.lParam);
288 			}
289 		}
290 	}
291 	m_htmlInventory->setColumnOrder(columnOrder);
292 }
293 
doMoveColumn(int distance)294 INT_PTR PartsListDialog::doMoveColumn(int distance)
295 {
296 	int selectedIndex = ListView_GetNextItem(m_hColumnList, -1, LVNI_SELECTED);
297 	int count = ListView_GetItemCount(m_hColumnList);
298 
299 	if (selectedIndex + distance < 0 ||
300 		selectedIndex + distance >= count)
301 	{
302 		// This shouldn't happen, but just in case...
303 		return 1;
304 	}
305 	else
306 	{
307 		LVITEM otherItem;
308 		LVITEM selectedItem;
309 		UCCHAR otherItemText[1024];
310 		UCCHAR selectedItemText[1024];
311 		BOOL otherCheckState;
312 		BOOL selectedCheckState;
313 
314 		otherItem.mask = selectedItem.mask = LVIF_TEXT | LVIF_PARAM;
315 		otherItem.iItem = selectedIndex + distance;
316 		selectedItem.iItem = selectedIndex;
317 		otherItem.iSubItem = selectedItem.iSubItem = 0;
318 		otherItem.pszText = otherItemText;
319 		selectedItem.pszText = selectedItemText;
320 		otherItem.cchTextMax = selectedItem.cchTextMax =
321 			COUNT_OF(otherItemText);
322 		ListView_GetItem(m_hColumnList, &otherItem);
323 		ListView_GetItem(m_hColumnList, &selectedItem);
324 		otherItem.iItem = selectedIndex;
325 		selectedItem.iItem = selectedIndex + distance;
326 		ListView_SetItem(m_hColumnList, &otherItem);
327 		ListView_SetItem(m_hColumnList, &selectedItem);
328 		otherCheckState = ListView_GetCheckState(m_hColumnList,
329 			selectedIndex + distance);
330 		selectedCheckState = ListView_GetCheckState(m_hColumnList,
331 			selectedIndex);
332 		if (otherCheckState != selectedCheckState)
333 		{
334 			// Swapping the states doesn't work right above; we apparently have
335 			// to use the set check macro.
336 			ListView_SetCheckState(m_hColumnList, selectedIndex + distance,
337 				selectedCheckState);
338 			ListView_SetCheckState(m_hColumnList, selectedIndex,
339 				otherCheckState);
340 		}
341 		// Select other item.  (Single select LV, so no need to deselect
342 		// the current item.
343 		ListView_SetItemState(m_hColumnList, selectedIndex + distance,
344 			LVIS_SELECTED, LVIS_SELECTED);
345 		return 0;
346 	}
347 }
348 
doClick(int controlId,HWND)349 INT_PTR PartsListDialog::doClick(int controlId, HWND /*hControl*/)
350 {
351 	switch (controlId)
352 	{
353 	case IDOK:
354 		m_modalReturn = IDOK;
355 		saveSettings();
356 		m_parentWindow->doDialogClose(m_hDlg);
357 		break;
358 	case IDCANCEL:
359 		m_parentWindow->doDialogClose(m_hDlg);
360 		break;
361 	case IDC_SHOW_MODEL:
362 		updateOverwriteCheck();
363 		break;
364 	case 42:	// Column order toolbar up button
365 		return doMoveColumn(-1);
366 		break;
367 	case 43:	// Column order toolbar down button
368 		return doMoveColumn(1);
369 		break;
370 	default:
371 		return 1;
372 		break;
373 	}
374 	return 0;
375 }
376 
doCommand(int controlId,int notifyCode,HWND hControl)377 INT_PTR PartsListDialog::doCommand(int controlId, int notifyCode, HWND hControl)
378 {
379 	if (notifyCode == BN_CLICKED)
380 	{
381 		return doClick(controlId, hControl);
382 	}
383 	return FALSE;
384 }
385 
doListViewItemChanged(int controlId,LPNMLISTVIEW)386 void PartsListDialog::doListViewItemChanged(int controlId, LPNMLISTVIEW /*pnmlv*/)
387 {
388 	if (controlId == IDC_COLUMN_ORDER_LIST)
389 	{
390 		int count = ListView_GetItemCount(m_hColumnList);
391 
392 		if (count > 1)
393 		{
394 			int selectedIndex = ListView_GetNextItem(m_hColumnList, -1,
395 				LVNI_SELECTED);
396 
397 			if (selectedIndex > 0)
398 			{
399 				// Enable up button
400 				SendMessage(m_hToolbar, TB_SETSTATE, 42,
401 					MAKELONG(TBSTATE_ENABLED, 0));
402 			}
403 			else
404 			{
405 				// Disable up button
406 				SendMessage(m_hToolbar, TB_SETSTATE, 42, MAKELONG(0, 0));
407 			}
408 			if (selectedIndex < count - 1 && selectedIndex >= 0)
409 			{
410 				// Enable down button
411 				SendMessage(m_hToolbar, TB_SETSTATE, 43,
412 					MAKELONG(TBSTATE_ENABLED, 0));
413 			}
414 			else
415 			{
416 				// Disable up button
417 				SendMessage(m_hToolbar, TB_SETSTATE, 43, MAKELONG(0, 0));
418 			}
419 		}
420 	}
421 }
422 
doNotify(int controlId,LPNMHDR pnmh)423 INT_PTR PartsListDialog::doNotify(int controlId, LPNMHDR pnmh)
424 {
425 	switch (pnmh->code)
426 	{
427 	case LVN_ITEMCHANGED:
428 		doListViewItemChanged(controlId, (LPNMLISTVIEW)pnmh);
429 		break;
430 	}
431 	return FALSE;
432 }
433 
registerWindowClass(void)434 void PartsListDialog::registerWindowClass(void)
435 {
436 	WNDCLASSEX windowClass;
437 	windowClass.cbSize = sizeof(windowClass);
438 
439 	if (!GetClassInfoEx(CUIWindow::getLanguageModule(), _UC("LDViewPartsListWindow"),
440 		&windowClass))
441 	{
442 		UCCHAR progressClassName[1024];
443 		// The load progress dialog doesn't have a custom window class.  The
444 		// default window class for dialogs had a window proc that does a bunch
445 		// of work that we need, so create a dummy window and grab the
446 		// information out of the dummy window's window class.  Then, replace
447 		// the bits that we want to replace.
448 		HWND hProgressWindow = m_parentWindow->createDialog(IDD_LOAD_PROGRESS);
449 
450 		GetClassName(hProgressWindow, progressClassName, COUNT_OF(progressClassName));
451 		windowClass.cbSize = sizeof(windowClass);
452 		GetClassInfoEx(CUIWindow::getLanguageModule(), progressClassName,
453 			&windowClass);
454 		windowClass.hIcon = LoadIcon(CUIWindow::getLanguageModule(),
455 			MAKEINTRESOURCE(IDI_APP_ICON));
456 		windowClass.lpszMenuName = NULL;
457 		windowClass.lpszClassName = _UC("LDViewPartsListWindow");
458 		RegisterClassEx(&windowClass);
459 		DestroyWindow(hProgressWindow);
460 	}
461 }
462