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