1 #include "ModelTreeDialog.h"
2 #include "ModelWindow.h"
3 #include "Resource.h"
4 #include <TCFoundation/mystring.h>
5 #include <TCFoundation/TCLocalStrings.h>
6 #include <TCFoundation/TCAlertManager.h>
7 #include <LDLoader/LDLMainModel.h>
8 #include <LDLib/LDModelTree.h>
9 #include <LDLib/LDUserDefaultsKeys.h>
10 #include <CUI/CUIWindowResizer.h>
11 #include <CUI/CUIColorButton.h>
12 #include <CommCtrl.h>
13 
14 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
15 #define new DEBUG_CLIENTBLOCK
16 #endif // _DEBUG
17 
18 #define SEARCH_TIMER 1
19 
ModelTreeDialog(HINSTANCE hInstance,HWND hParentWindow)20 ModelTreeDialog::ModelTreeDialog(HINSTANCE hInstance, HWND hParentWindow):
21 CUIDialog(hInstance, hParentWindow),
22 m_modelWindow(NULL),
23 m_model(NULL),
24 m_modelTree(NULL),
25 m_resizer(NULL),
26 m_optionsShown(true),
27 m_highlight(TCUserDefaults::boolForKey(MODEL_TREE_HIGHLIGHT_KEY, false, false)),
28 m_clearing(false)
29 {
30 	COLORREF defHighlightColor = RGB(160, 224, 255);
31 	long highlightColor =
32 		TCUserDefaults::longForKey(MODEL_TREE_HIGHLIGHT_COLOR_KEY,
33 		defHighlightColor, false);
34 	LongVector customColors;
35 
36 	customColors = TCUserDefaults::longVectorForKey(MODEL_TREE_CUST_COLORS_KEY,
37 		customColors, false);
38 	if (customColors.size() == 0)
39 	{
40 		// Put the default highlight color into the list of custom colors.
41 		customColors.resize(16);
42 		customColors[0] = defHighlightColor;
43 		TCUserDefaults::setLongVectorForKey(customColors,
44 			MODEL_TREE_CUST_COLORS_KEY, false);
45 	}
46 	m_highlightR = GetRValue(highlightColor);
47 	m_highlightG = GetGValue(highlightColor);
48 	m_highlightB = GetBValue(highlightColor);
49 	TCAlertManager::registerHandler(ModelWindow::alertClass(), this,
50 		(TCAlertCallback)&ModelTreeDialog::modelAlertCallback);
51 }
52 
~ModelTreeDialog(void)53 ModelTreeDialog::~ModelTreeDialog(void)
54 {
55 }
56 
dealloc(void)57 void ModelTreeDialog::dealloc(void)
58 {
59 	TCAlertManager::unregisterHandler(this);
60 	if (hWindow)
61 	{
62 		DestroyWindow(hWindow);
63 	}
64 	TCObject::release(m_colorButton);
65 	TCObject::release(m_modelWindow);
66 	TCObject::release(m_modelTree);
67 	TCObject::release(m_model);
68 	TCObject::release(m_resizer);
69 	CUIDialog::dealloc();
70 }
71 
setModel(LDLMainModel * model)72 void ModelTreeDialog::setModel(LDLMainModel *model)
73 {
74 	if (model != m_model)
75 	{
76 		clearTreeView();
77 		TCObject::release(m_model);
78 		TCObject::release(m_modelTree);
79 		m_modelTree = NULL;
80 		m_model = model;
81 		TCObject::retain(m_model);
82 	}
83 }
84 
modelAlertCallback(TCAlert * alert)85 void ModelTreeDialog::modelAlertCallback(TCAlert *alert)
86 {
87 	if (alert->getSender() == m_modelWindow)
88 	{
89 		if (ucstrcmp(alert->getMessageUC(), _UC("ModelLoaded")) == 0)
90 		{
91 			setModel(m_modelWindow->getModelViewer()->getMainModel());
92 			fillTreeView();
93 		}
94 		else if (ucstrcmp(alert->getMessageUC(), _UC("ModelLoadCanceled")) == 0)
95 		{
96 			setModel(NULL);
97 			fillTreeView();
98 		}
99 	}
100 }
101 
setModelWindow(ModelWindow * modelWindow)102 void ModelTreeDialog::setModelWindow(ModelWindow *modelWindow)
103 {
104 	if (modelWindow != m_modelWindow)
105 	{
106 		if (m_modelWindow)
107 		{
108 			m_modelWindow->release();
109 		}
110 		m_modelWindow = modelWindow;
111 		TCObject::retain(m_modelWindow);
112 	}
113 	setModel(m_modelWindow->getModelViewer()->getMainModel());
114 }
115 
show(ModelWindow * modelWindow,HWND hParentWnd)116 void ModelTreeDialog::show(ModelWindow *modelWindow, HWND hParentWnd /*= NULL*/)
117 {
118 	setModelWindow(modelWindow);
119 	if (hWindow == NULL)
120 	{
121 		createDialog(IDD_MODELTREE, hParentWnd);
122 	}
123 	ShowWindow(hWindow, SW_SHOW);
124 	fillTreeView();
125 }
126 
doTreeItemExpanding(LPNMTREEVIEW notification)127 LRESULT ModelTreeDialog::doTreeItemExpanding(LPNMTREEVIEW notification)
128 {
129 	if (notification->action == TVE_EXPAND)
130 	{
131 		LDModelTree *tree = (LDModelTree *)notification->itemNew.lParam;
132 
133 		if (!tree->getViewPopulated())
134 		{
135 			addChildren(notification->itemNew.hItem, tree);
136 			tree->setViewPopulated(true);
137 		}
138 		return 0;
139 	}
140 	return 1;
141 }
142 
highlightItem(HTREEITEM hItem)143 void ModelTreeDialog::highlightItem(HTREEITEM hItem)
144 {
145 	LDModelTree *tree = getItemTree(hItem);
146 
147 	if (tree != NULL)
148 	{
149 		m_modelWindow->getModelViewer()->setHighlightColor(m_highlightR,
150 			m_highlightG, m_highlightB, false);
151 		m_modelWindow->getModelViewer()->setHighlightPaths(
152 			tree->getTreePath());
153 		m_searchPath = tree->getTreePath();
154 	}
155 	else
156 	{
157 		m_modelWindow->getModelViewer()->setHighlightPaths("");
158 		m_searchPath = "";
159 	}
160 }
161 
doTreeSelChanged(LPNMTREEVIEW notification)162 LRESULT ModelTreeDialog::doTreeSelChanged(LPNMTREEVIEW notification)
163 {
164 	if (!m_clearing)
165 	{
166 		if (m_highlight)
167 		{
168 			highlightItem(notification->itemNew.hItem);
169 		}
170 		updateStatusText();
171 	}
172 	return 1;	// Ignored
173 }
174 
doHighlightColorChanged(void)175 LRESULT ModelTreeDialog::doHighlightColorChanged(void)
176 {
177 	LDrawModelViewer *modelViewer = m_modelWindow->getModelViewer();
178 	m_colorButton->getColor(m_highlightR, m_highlightG, m_highlightB);
179 	modelViewer->setHighlightColor(m_highlightR, m_highlightG, m_highlightB);
180 	TCUserDefaults::setLongForKey(RGB(m_highlightR, m_highlightG, m_highlightB),
181 		MODEL_TREE_HIGHLIGHT_COLOR_KEY, false);
182 	return 0;
183 }
184 
doNotify(int controlId,LPNMHDR notification)185 LRESULT ModelTreeDialog::doNotify(int controlId, LPNMHDR notification)
186 {
187 	if (controlId == IDC_MODEL_TREE)
188 	{
189 		switch (notification->code)
190 		{
191 		case TVN_ITEMEXPANDINGUC:
192 			return doTreeItemExpanding((LPNMTREEVIEW)notification);
193 		case TVN_KEYDOWN:
194 			return doTreeKeyDown((LPNMTVKEYDOWN)notification);
195 		case TVN_SELCHANGEDUC:
196 			return doTreeSelChanged((LPNMTREEVIEW)notification);
197 		case NM_CUSTOMDRAW:
198 			return doTreeCustomDraw((LPNMTVCUSTOMDRAW)notification);
199 		}
200 	}
201 	else if (controlId == IDC_HIGHLIGHT_COLOR)
202 	{
203 		if (notification->code == CCBN_COLOR_CHANGED)
204 		{
205 			return doHighlightColorChanged();
206 		}
207 	}
208 	return 1;
209 }
210 
addChildren(HTREEITEM parent,const LDModelTree * tree)211 void ModelTreeDialog::addChildren(HTREEITEM parent, const LDModelTree *tree)
212 {
213 	if (tree != NULL && tree->hasChildren(true))
214 	{
215 		const LDModelTreeArray *lchildren = tree->getChildren(true);
216 		int count = lchildren->getCount();
217 
218 		for (int i = 0; i < count; i++)
219 		{
220 			const LDModelTree *child = (*lchildren)[i];
221 			addLine(parent, child);
222 		}
223 	}
224 }
225 
addLine(HTREEITEM parent,const LDModelTree * tree)226 HTREEITEM ModelTreeDialog::addLine(HTREEITEM parent, const LDModelTree *tree)
227 {
228 	TVINSERTSTRUCTUC insertStruct;
229 	TVITEMEXUC item;
230 	HTREEITEM hNewItem;
231 
232 	memset(&item, 0, sizeof(item));
233 	item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_CHILDREN;
234 	item.cChildren = tree->getNumChildren(true);
235 	item.pszText = copyString(tree->getTextUC().c_str());
236 	item.lParam = (LPARAM)tree;
237 	insertStruct.hParent = parent;
238 	insertStruct.hInsertAfter = TVI_LAST;
239 	insertStruct.itemex = item;
240 	hNewItem = (HTREEITEM)::SendMessage(m_hTreeView, TVM_INSERTITEMUC, 0,
241 		(LPARAM)&insertStruct);
242 	delete item.pszText;
243 	return hNewItem;
244 }
245 
updateLineChecks(void)246 void ModelTreeDialog::updateLineChecks(void)
247 {
248 	for (int i = LDLLineTypeComment; i <= LDLLineTypeUnknown; i++)
249 	{
250 		LDLLineType lineType = (LDLLineType)i;
251 		bool checked = false;
252 		BOOL enabled = m_model != NULL;
253 
254 		if (m_modelTree)
255 		{
256 			checked = m_modelTree->getShowLineType(lineType);
257 		}
258 		checkSet(m_checkIds[lineType], checked);
259 		EnableWindow(m_lineChecks[i], enabled);
260 	}
261 }
262 
doLineCheck(UINT checkId,LDLLineType lineType)263 LRESULT ModelTreeDialog::doLineCheck(UINT checkId, LDLLineType lineType)
264 {
265 	if (m_modelTree)
266 	{
267 		m_modelTree->setShowLineType(lineType, checkGet(checkId));
268 		refreshTreeView();
269 	}
270 	return 0;
271 }
272 
doHighlightCheck(void)273 LRESULT ModelTreeDialog::doHighlightCheck(void)
274 {
275 	m_highlight = checkGet(IDC_HIGHLIGHT);
276 	if (m_highlight)
277 	{
278 		highlightItem(TreeView_GetSelection(m_hTreeView));
279 	}
280 	else
281 	{
282 		m_modelWindow->getModelViewer()->setHighlightPaths("");
283 	}
284 	TCUserDefaults::setBoolForKey(m_highlight, MODEL_TREE_HIGHLIGHT_KEY, false);
285 	return 0;
286 }
287 
getItemTree(HTREEITEM hItem)288 LDModelTree* ModelTreeDialog::getItemTree(HTREEITEM hItem)
289 {
290 	if (!hItem)
291 	{
292 		return NULL;
293 	}
294 	TVITEMEX item;
295 
296 	memset(&item, 0, sizeof(item));
297 	item.mask = TVIF_PARAM;
298 	item.hItem = hItem;
299 	if (TreeView_GetItem(m_hTreeView, &item))
300 	{
301 		return (LDModelTree *)item.lParam;
302 	}
303 	return NULL;
304 }
305 
doSearch(LDModelTree::SearchMode mode,bool updateFocus)306 LRESULT ModelTreeDialog::doSearch(LDModelTree::SearchMode mode, bool updateFocus)
307 {
308 	ucstring searchString;
309 	windowGetText(IDC_SEARCH, searchString);
310 	std::string pathString = m_searchPath;
311 	if (m_modelTree->search(searchString, pathString, mode))
312 	{
313 		selectFromHighlightPath(pathString);
314 		if (updateFocus)
315 		{
316 			SetFocus(GetDlgItem(hWindow, IDC_MODEL_TREE));
317 		}
318 	}
319 	else
320 	{
321 		TreeView_SelectItem(m_hTreeView, NULL);
322 	}
323 	return 0;
324 }
325 
doTimer(UINT_PTR timerID)326 LRESULT ModelTreeDialog::doTimer(UINT_PTR timerID)
327 {
328 	switch (timerID)
329 	{
330 	case SEARCH_TIMER:
331 		killTimer(SEARCH_TIMER);
332 		doSearch(LDModelTree::SearchMode::SMType, false);
333 		break;
334 	}
335 	return 0;
336 }
337 
doSearchChange(void)338 LRESULT ModelTreeDialog::doSearchChange(void)
339 {
340 	killTimer(SEARCH_TIMER);
341 	setTimer(SEARCH_TIMER, 500);
342 	return 0;
343 }
344 
doCommand(int notifyCode,int commandId,HWND control)345 LRESULT ModelTreeDialog::doCommand(
346 	int notifyCode,
347 	int commandId,
348 	HWND control)
349 {
350 	switch (commandId)
351 	{
352 	case IDC_OPTIONS:
353 		return doToggleOptions();
354 	case IDC_HIGHLIGHT:
355 		return doHighlightCheck();
356 	case IDC_PREV:
357 		return doSearch(LDModelTree::SearchMode::SMPrevious, true);
358 	case IDC_NEXT:
359 		return doSearch(LDModelTree::SearchMode::SMNext, true);
360 	case IDC_SEARCH:
361 		if (notifyCode == EN_CHANGE)
362 		{
363 			return doSearchChange();
364 		}
365 		break;
366 	case IDOK:
367 		if (GetFocus() == GetDlgItem(hWindow, IDC_SEARCH))
368 		{
369 			killTimer(SEARCH_TIMER);
370 			return doSearch(LDModelTree::SearchMode::SMType, true);
371 		}
372 		break;
373 	default:
374 		{
375 			UIntLineTypeMap::const_iterator it = m_checkLineTypes.find(commandId);
376 
377 			if (it != m_checkLineTypes.end())
378 			{
379 				return doLineCheck(it->first, it->second);
380 			}
381 		}
382 		break;
383 	}
384 	return CUIDialog::doCommand(notifyCode, commandId, control);
385 }
386 
clearTreeView(void)387 void ModelTreeDialog::clearTreeView(void)
388 {
389 	m_clearing = true;
390 	SendMessage(m_hTreeView, WM_SETREDRAW, FALSE, 0);
391 	TreeView_DeleteAllItems(m_hTreeView);
392 	SendMessage(m_hTreeView, WM_SETREDRAW, TRUE, 0);
393 	TreeView_SelectItem(m_hTreeView, NULL);
394 	m_clearing = false;
395 	updateStatusText();
396 }
397 
getChild(HTREEITEM hParent,int index)398 HTREEITEM ModelTreeDialog::getChild(HTREEITEM hParent, int index)
399 {
400 	HTREEITEM hItem;
401 
402 	hItem = TreeView_GetChild(m_hTreeView, hParent);
403 	for (int i = 1; i <= index; i++)
404 	{
405 		hItem = TreeView_GetNextSibling(m_hTreeView, hItem);
406 	}
407 	return hItem;
408 }
409 
selectFromHighlightPath(std::string path)410 void ModelTreeDialog::selectFromHighlightPath(std::string path)
411 {
412 	HTREEITEM hItem = NULL;
413 
414 	path = m_modelTree->adjustHighlightPath(path);
415 	while (path.size() > 0)
416 	{
417 		int lineNumber = atoi(&path[1]) - 1;
418 
419 		hItem = getChild(hItem, lineNumber);
420 		if (hItem != NULL)
421 		{
422 			size_t index = path.find('/', 1);
423 			if (index < path.size())
424 			{
425 				TreeView_Expand(m_hTreeView, hItem, TVE_EXPAND);
426 				path = path.substr(index);
427 			}
428 			else
429 			{
430 				LDModelTree *tree = getItemTree(hItem);
431 				if (tree != NULL)
432 				{
433 					m_searchPath = tree->getTreePath();
434 				}
435 				TreeView_SelectItem(m_hTreeView, hItem);
436 				path = "";
437 			}
438 		}
439 		else
440 		{
441 			return;
442 		}
443 	}
444 }
445 
refreshTreeView(void)446 void ModelTreeDialog::refreshTreeView(void)
447 {
448 	// The following has to be a copy, because the selection triggers the
449 	// list to disappear out from under us.
450 	StringList paths = m_modelWindow->getModelViewer()->getHighlightPaths();
451 
452 	clearTreeView();
453 	SendMessage(m_hTreeView, WM_SETREDRAW, FALSE, 0);
454 	addChildren(NULL, m_modelTree);
455 	SendMessage(m_hTreeView, WM_SETREDRAW, TRUE, 0);
456 	RedrawWindow(m_hTreeView, NULL, NULL, RDW_INVALIDATE);
457 	if (m_modelTree != NULL)
458 	{
459 		for (StringList::const_iterator it = paths.begin(); it != paths.end();
460 			it++)
461 		{
462 			selectFromHighlightPath(*it);
463 		}
464 	}
465 }
466 
fillTreeView(void)467 void ModelTreeDialog::fillTreeView(void)
468 {
469 	if (m_modelTree == NULL && IsWindowVisible(hWindow))
470 	{
471 		if (m_model)
472 		{
473 			m_modelTree = new LDModelTree(m_model);
474 		}
475 		updateLineChecks();
476 		refreshTreeView();
477 	}
478 }
479 
setupLineCheck(UINT checkId,LDLLineType lineType)480 void ModelTreeDialog::setupLineCheck(UINT checkId, LDLLineType lineType)
481 {
482 	m_lineChecks[lineType] = GetDlgItem(hWindow, checkId);
483 	m_checkLineTypes[checkId] = lineType;
484 	m_checkIds[lineType] = checkId;
485 	m_resizer->addSubWindow(checkId, CUIFloatLeft | CUIFloatBottom);
486 }
487 
adjustWindow(int widthDelta)488 void ModelTreeDialog::adjustWindow(int widthDelta)
489 {
490 	WINDOWPLACEMENT wp;
491 	int showCommand;
492 
493 	if (widthDelta > 0)
494 	{
495 		showCommand = SW_SHOW;
496 	}
497 	else
498 	{
499 		showCommand = SW_HIDE;
500 	}
501 	minWidth += widthDelta;
502 	GetWindowPlacement(hWindow, &wp);
503 	m_resizer->setOriginalWidth(m_resizer->getOriginalWidth() + widthDelta);
504 	if (wp.showCmd == SW_MAXIMIZE)
505 	{
506 		RECT clientRect;
507 
508 		GetClientRect(hWindow, &clientRect);
509 		m_resizer->resize(clientRect.right - clientRect.left,
510 			clientRect.bottom - clientRect.top);
511 	}
512 	else
513 	{
514 		RECT windowRect;
515 
516 		GetWindowRect(hWindow, &windowRect);
517 		windowRect.right += widthDelta;
518 		MoveWindow(hWindow, windowRect.left, windowRect.top,
519 			windowRect.right - windowRect.left,
520 			windowRect.bottom - windowRect.top, TRUE);
521 	}
522 	for (size_t i = 0; i < m_lineChecks.size(); i++)
523 	{
524 		ShowWindow(m_lineChecks[i], showCommand);
525 	}
526 	//positionResizeGrip(m_hResizeGrip);
527 }
528 
swapWindowText(UCCHAR oldChar,UCCHAR newChar)529 void ModelTreeDialog::swapWindowText(UCCHAR oldChar, UCCHAR newChar)
530 {
531 	ucstring text;
532 
533 	windowGetText(IDC_OPTIONS, text);
534 	replaceStringCharacter(&text[0], oldChar, newChar);
535 	windowSetText(IDC_OPTIONS, text);
536 }
537 
hideOptions(void)538 void ModelTreeDialog::hideOptions(void)
539 {
540 	adjustWindow(-m_optionsDelta);
541 	swapWindowText('<', '>');
542 	m_optionsShown = false;
543 }
544 
showOptions(void)545 void ModelTreeDialog::showOptions(void)
546 {
547 	adjustWindow(m_optionsDelta);
548 	swapWindowText('>', '<');
549 	m_optionsShown = true;
550 }
551 
doToggleOptions(void)552 LRESULT ModelTreeDialog::doToggleOptions(void)
553 {
554 	if (m_optionsShown)
555 	{
556 		hideOptions();
557 	}
558 	else
559 	{
560 		showOptions();
561 	}
562 	TCUserDefaults::setBoolForKey(m_optionsShown, MODEL_TREE_OPTIONS_SHOWN_KEY,
563 		false);
564 	return 0;
565 }
566 
addToolToTooltip(int controlId,const ucstring & tooltipText)567 void ModelTreeDialog::addToolToTooltip(int controlId, const ucstring& tooltipText)
568 {
569 	HWND hControl = GetDlgItem(hWindow, controlId);
570 	TOOLINFOUC ti;
571 
572 	memset(&ti, 0, sizeof(ti));
573 	ti.cbSize = sizeof(ti);
574 	ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
575 	ti.hwnd = hWindow;
576 	ti.uId = (UINT_PTR)hControl;
577 	ucstring tooltipTextCopy = tooltipText;
578 	ti.lpszText = &tooltipTextCopy[0];
579 	::SendMessage(m_hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
580 }
581 
doInitDialog(HWND hKbControl)582 BOOL ModelTreeDialog::doInitDialog(HWND hKbControl)
583 {
584 	RECT optionsRect;
585 	RECT clientRect;
586 
587 	m_colorButton = new CUIColorButton(GetDlgItem(hWindow,
588 		IDC_HIGHLIGHT_COLOR), MODEL_TREE_CUST_COLORS_KEY, m_highlightR,
589 		m_highlightG, m_highlightB);
590 	setIcon(IDI_APP_ICON);
591 	m_hTreeView = GetDlgItem(hWindow, IDC_MODEL_TREE);
592 
593 	m_hTooltip = CUIWindow::createWindowExUC(0, TOOLTIPS_CLASSUC,
594 		NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP /*| TTS_BALLOON*/,
595 		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
596 		hWindow, NULL, hInstance, NULL);
597 	SetWindowPos(m_hTooltip, HWND_TOPMOST, 0, 0, 0, 0,
598 		SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
599 	if (haveWindowsVistaOrLater())
600 	{
601 		std::wstring magnifier;
602 		if (haveWindows7OrLater())
603 		{
604 			// Windows 7 is the first version to support emojis.
605 			// Note: EM_SETCUEBANNER always expects Unicode, so having a hard-coded Unicode
606 			// magnifier works as long as the Windows version support emojis.
607 			magnifier = L"\U0001F50D ";
608 		}
609 		std::wstring cue = magnifier + ls(L"Search");
610 		SendDlgItemMessage(hWindow, IDC_SEARCH, EM_SETCUEBANNER, TRUE, (LPARAM)cue.c_str());
611 	}
612 	addToolToTooltip(IDC_PREV, ls(_UC("Previous")));
613 	addToolToTooltip(IDC_NEXT, ls(_UC("Next")));
614 
615 	m_resizer = new CUIWindowResizer;
616 	m_resizer->setHWindow(hWindow);
617 	m_resizer->addSubWindow(IDC_SEARCH, CUISizeHorizontal | CUIFloatBottom);
618 	m_resizer->addSubWindow(IDC_PREV, CUIFloatLeft | CUIFloatBottom);
619 	m_resizer->addSubWindow(IDC_NEXT, CUIFloatLeft | CUIFloatBottom);
620 	m_resizer->addSubWindow(IDC_MODEL_TREE,
621 		CUISizeHorizontal | CUISizeVertical);
622 	m_resizer->addSubWindow(IDC_SHOW_BOX, CUIFloatLeft | CUIFloatBottom);
623 	m_resizer->addSubWindow(IDC_OPTIONS, CUIFloatLeft | CUIFloatTop);
624 	m_resizer->addSubWindow(IDC_HIGHLIGHT, CUIFloatRight | CUIFloatTop);
625 	m_resizer->addSubWindow(IDC_HIGHLIGHT_COLOR, CUIFloatRight | CUIFloatTop);
626 	m_lineChecks.resize(LDLLineTypeUnknown + 1);
627 	setupLineCheck(IDC_COMMENT, LDLLineTypeComment);
628 	setupLineCheck(IDC_MODEL, LDLLineTypeModel);
629 	setupLineCheck(IDC_LINE, LDLLineTypeLine);
630 	setupLineCheck(IDC_TRIANGLE, LDLLineTypeTriangle);
631 	setupLineCheck(IDC_QUAD, LDLLineTypeQuad);
632 	setupLineCheck(IDC_CONDITIONAL, LDLLineTypeConditionalLine);
633 	setupLineCheck(IDC_EMPTY, LDLLineTypeEmpty);
634 	setupLineCheck(IDC_UNKNOWN, LDLLineTypeUnknown);
635 	GetWindowRect(GetDlgItem(hWindow, IDC_SHOW_BOX), &optionsRect);
636 	screenToClient(hWindow, &optionsRect);
637 	GetClientRect(hWindow, &clientRect);
638 	m_optionsDelta = clientRect.right - optionsRect.left;
639 	setMinSize(clientRect.right, clientRect.bottom, true);
640 	if (!TCUserDefaults::boolForKey(MODEL_TREE_OPTIONS_SHOWN_KEY, true, false))
641 	{
642 		hideOptions();
643 	}
644 	checkSet(IDC_HIGHLIGHT, m_highlight);
645 	initStatusBar();
646 	setAutosaveName("ModelTreeDialog");
647 	return CUIDialog::doInitDialog(hKbControl);
648 }
649 
updateStatusText(void)650 void ModelTreeDialog::updateStatusText(void)
651 {
652 	HTREEITEM hItem = TreeView_GetSelection(m_hTreeView);
653 	LDModelTree *tree = getItemTree(hItem);
654 
655 	if (tree != NULL)
656 	{
657 		statusBarSetText(m_hStatus, 0, tree->getStatusText());
658 		return;
659 	}
660 	statusBarSetText(m_hStatus, 0, ls(_UC("NoSelection")));
661 }
662 
initStatusBar(void)663 void ModelTreeDialog::initStatusBar(void)
664 {
665 	int parts[] = {-1};
666 
667 	m_hStatus = ::CreateWindow(STATUSCLASSNAME, _UC(""),
668 		WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 10, 10, hWindow, NULL,
669 		hInstance, 0);
670 	statusBarSetParts(m_hStatus, 1, parts);
671 	updateStatusText();
672 }
673 
doClose(void)674 LRESULT ModelTreeDialog::doClose(void)
675 {
676 	if (m_highlight)
677 	{
678 		m_modelWindow->getModelViewer()->setHighlightPaths("");
679 	}
680 	showWindow(SW_HIDE);
681 	return 0;
682 }
683 
doSize(WPARAM sizeType,int newWidth,int newHeight)684 LRESULT ModelTreeDialog::doSize(WPARAM sizeType, int newWidth, int newHeight)
685 {
686 	if (sizeType != SIZE_MINIMIZED)
687 	{
688 		m_resizer->resize(newWidth, newHeight);
689 		//positionResizeGrip(m_hResizeGrip, newWidth, newHeight);
690 		SendMessage(m_hStatus, WM_SIZE, sizeType,
691 			MAKELPARAM(newWidth, newHeight));
692 	}
693 	return CUIDialog::doSize(sizeType, newWidth, newHeight);
694 }
695 
doTreeCustomDraw(LPNMTVCUSTOMDRAW notification)696 LRESULT ModelTreeDialog::doTreeCustomDraw(LPNMTVCUSTOMDRAW notification)
697 {
698 	if (notification->nmcd.dwDrawStage == CDDS_PREPAINT)
699 	{
700 		SetWindowLongPtr(hWindow, DWLP_MSGRESULT, CDRF_NOTIFYITEMDRAW);
701 		return TRUE;
702 	}
703 	else if (notification->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
704 	{
705 		LDModelTree *itemTree = (LDModelTree *)notification->nmcd.lItemlParam;
706 
707 		if (itemTree)
708 		{
709 			TCByte r, g, b;
710 
711 			if ((notification->nmcd.uItemState & CDIS_SELECTED) == 0 &&
712 				itemTree->getTextRGB(r, g, b))
713 			{
714 				notification->clrText = RGB(r, g, b);
715 			}
716 			SetWindowLongPtr(hWindow, DWLP_MSGRESULT, CDRF_DODEFAULT);
717 			return TRUE;
718 		}
719 	}
720 	return FALSE;
721 }
722 
doTreeKeyDown(LPNMTVKEYDOWN notification)723 LRESULT ModelTreeDialog::doTreeKeyDown(LPNMTVKEYDOWN notification)
724 {
725 	if (notification->wVKey == 'C' && (GetKeyState(VK_CONTROL) & 0x8000))
726 	{
727 		if (doTreeCopy())
728 		{
729 			return 0;
730 		}
731 	}
732 	return 1;
733 }
734 
doTreeCopy(void)735 BOOL ModelTreeDialog::doTreeCopy(void)
736 {
737 	HTREEITEM hItem = TreeView_GetSelection(m_hTreeView);
738 	LDModelTree *tree = getItemTree(hItem);
739 
740 	if (tree != NULL)
741 	{
742 		std::string text = tree->getText();
743 
744 		if (tree->getLineType() == LDLLineTypeEmpty)
745 		{
746 			text = "";
747 		}
748 		text += "\r\n";
749 		if (copyToClipboard(text.c_str()))
750 		{
751 			SetWindowLongPtr(hWindow, DWLP_MSGRESULT, TRUE);
752 			return TRUE;
753 		}
754 	}
755 	return FALSE;
756 }
757 
doOK(void)758 void ModelTreeDialog::doOK(void)
759 {
760 	// Don't do anything.
761 }
762