1 #include "ToolbarStrip.h"
2 #include "Resource.h"
3 #include "LDViewWindow.h"
4 #include "ModelWindow.h"
5 #include "LDViewPreferences.h"
6 #include <TCFoundation/TCJpegOptions.h>
7 #include <TCFoundation/mystring.h>
8 #include <TCFoundation/TCLocalStrings.h>
9 #include <TCFoundation/TCAlertManager.h>
10 #include <LDLib/LDUserDefaultsKeys.h>
11 #include <CUI/CUIScaler.h>
12 #if _MSC_VER >= 1300 && !defined(TC_NO_UNICODE)	// VC >= VC 2003
13 #define min(x, y) ((x) < (y) ? (x) : (y))
14 #define max(x, y) ((x) > (y) ? (x) : (y))
15 #pragma warning(push)
16 #pragma warning(disable:4458)
17 #include <gdiplus.h>
18 #include <gdiplusflat.h>
19 #pragma warning(pop)
20 #define USE_GDIPLUS
21 #endif // VC >= VC 2005
22 
23 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
24 #define new DEBUG_CLIENTBLOCK
25 #endif // _DEBUG
26 
27 
28 #define NUM_DEFAULT_TB_BUTTONS 13
29 #define STEP_COUNT_CHANGED_TIMER 42
30 
31 #ifdef USE_GDIPLUS
32 
33 typedef Gdiplus::Status (WINAPI *PFNGDIPLUSSTARTUP)(
34     OUT ULONG_PTR *token,
35     const Gdiplus::GdiplusStartupInput *input,
36     OUT Gdiplus::GdiplusStartupOutput *output);
37 typedef VOID (WINAPI *PFNGDIPLUSSHUTDOWN)(ULONG_PTR token);
38 typedef Gdiplus::GpStatus (WINGDIPAPI *PFNGDIPCREATEBITMAPFROMHICON)(
39 	HICON hicon, Gdiplus::GpBitmap** bitmap);
40 typedef Gdiplus::GpStatus (WINGDIPAPI *PFNGDIPCREATEHBITMAPFROMBITMAP)(
41 	Gdiplus::GpBitmap* bitmap, HBITMAP* hbmReturn, Gdiplus::ARGB background);
42 typedef Gdiplus::GpStatus (WINGDIPAPI *PFNGDIPDISPOSEIMAGE)(
43 	Gdiplus::GpImage *image);
44 
45 static PFNGDIPLUSSTARTUP GdiplusStartup = NULL;
46 static PFNGDIPLUSSHUTDOWN GdiplusShutdown = NULL;
47 static PFNGDIPCREATEBITMAPFROMHICON GdipCreateBitmapFromHICON = NULL;
48 static PFNGDIPCREATEHBITMAPFROMBITMAP GdipCreateHBITMAPFromBitmap = NULL;
49 static PFNGDIPDISPOSEIMAGE GdipDisposeImage = NULL;
50 #endif // USE_GDIPLUS
51 
ToolbarStrip(HINSTANCE hInstance)52 ToolbarStrip::ToolbarStrip(HINSTANCE hInstance):
53 CUIDialog(hInstance),
54 m_stdBitmapStartId(-1),
55 m_tbBitmapStartId(-1),
56 m_numSteps(0),
57 m_hDeactivatedTooltip(NULL),
58 m_hGdiPlus(NULL),
59 m_showMain(TCUserDefaults::boolForKey(SHOW_MAIN_TOOLBAR_KEY, true, false)),
60 m_showSteps(TCUserDefaults::boolForKey(SHOW_STEPS_TOOLBAR_KEY, true, false))
61 {
62 	ModelWindow::initCommonControls(ICC_BAR_CLASSES | ICC_WIN95_CLASSES);
63 	TCAlertManager::registerHandler(ModelWindow::alertClass(), this,
64 		(TCAlertCallback)&ToolbarStrip::modelAlertCallback);
65 	m_commandMap[ID_TOOLS_ERRORS] = IDR_TB_ERRORS;
66 	m_commandMap[ID_VIEW_EXAMINE] = IDR_TB_EXAMINE;
67 	m_commandMap[ID_VIEW_EXAMINE_LAT_LONG] = IDR_TB_LATLONROT;
68 	m_commandMap[ID_VIEW_FLYTHROUGH] = IDR_TB_FLYTHROUGH;
69 	m_commandMap[ID_VIEW_WALK] = IDR_TB_WALK;
70 	m_commandMap[ID_VIEW_FULLSCREEN] = IDR_TB_FULLSCREEN;
71 	m_commandMap[ID_FILE_OPEN] = IDR_TB_OPEN;
72 	m_commandMap[ID_EDIT_PREFERENCES] = IDR_TB_PREFERENCES;
73 	m_commandMap[ID_FILE_RELOAD] = IDR_TB_RELOAD;
74 	m_commandMap[ID_VIEW_RIGHTSIDEUP] = IDR_TB_RIGHTSIDEUP;
75 	m_commandMap[ID_FILE_SAVE] = IDR_TB_SAVE;
76 	m_commandMap[ID_VIEW_ZOOMTOFIT] = IDR_TB_ZOOMTOFIT;
77 	m_commandMap[ID_FIRST_STEP] = IDR_TB_FIRST_STEP;
78 	m_commandMap[ID_LAST_STEP] = IDR_TB_LAST_STEP;
79 	m_commandMap[ID_NEXT_STEP] = IDR_TB_NEXT_STEP;
80 	m_commandMap[ID_PREV_STEP] = IDR_TB_PREV_STEP;
81 	m_commandMap[ID_HELP_CONTENTS] = IDR_TB_HELP;
82 	m_commandMap[ID_TOOLS_MODELTREE] = IDR_TB_MODELTREE;
83 	m_commandMap[ID_TOOLS_BOUNDINGBOX] = IDR_TB_MODELBBOX;
84 	m_commandMap[ID_VIEW_ALWAYSONTOP] = IDR_TB_TOPMOST;
85 	m_commandMap[ID_VIEW_FRONT] = IDR_TB_VIEW_FRONT;
86 	m_commandMap[ID_VIEW_BACK] = IDR_TB_VIEW_BACK;
87 	m_commandMap[ID_VIEW_LEFT] = IDR_TB_VIEW_LEFT;
88 	m_commandMap[ID_VIEW_RIGHT] = IDR_TB_VIEW_RIGHT;
89 	m_commandMap[ID_VIEW_TOP] = IDR_TB_VIEW_TOP;
90 	m_commandMap[ID_VIEW_BOTTOM] = IDR_TB_VIEW_BOTTOM;
91 	m_commandMap[ID_VIEW_ISO] = IDR_TB_VIEW_2_3RDS;
92 	m_commandMap[ID_VIEW_SPECIFYLATLON] = IDR_TB_LATLON;
93 	m_commandMap[ID_PRIMITIVES_TEXTURESTUDS] = IDR_TB_STUD;
94 	m_commandMap[ID_PRIMITIVES_TEXMAPS] = IDR_TB_TEXMAPS;
95 	m_commandMap[ID_FILE_EXPORT] = IDR_TB_EXPORT;
96 	m_commandMap[ID_FILE_PRINT] = IDR_TB_PRINT;
97 	m_commandMap[ID_TOOLS_PARTSLIST] = IDR_TB_PARTSLIST;
98 	m_commandMap[ID_TOOLS_MPD] = IDR_TB_MPD;
99 	m_commandMap[ID_TOOLS_POV_CAMERA] = IDR_TB_POVCAMERA;
100 }
101 
~ToolbarStrip(void)102 ToolbarStrip::~ToolbarStrip(void)
103 {
104 }
105 
dealloc(void)106 void ToolbarStrip::dealloc(void)
107 {
108 	if (m_hGdiPlus != NULL)
109 	{
110 		FreeLibrary(m_hGdiPlus);
111 		m_hGdiPlus = NULL;
112 	}
113 	for (size_t i = 0; i < m_imageLists.size(); i++)
114 	{
115 		ImageList_Destroy(m_imageLists[i]);
116 	}
117 	TCAlertManager::unregisterHandler(this);
118 	m_prefs->release();
119 	CUIDialog::dealloc();
120 }
121 
modelAlertCallback(TCAlert * alert)122 void ToolbarStrip::modelAlertCallback(TCAlert *alert)
123 {
124 	if (alert->getSender() == m_ldviewWindow->getModelWindow())
125 	{
126 		if (ucstrcmp(alert->getMessageUC(), _UC("ModelLoaded")) == 0 ||
127 			ucstrcmp(alert->getMessageUC(), _UC("ModelLoadCanceled")) == 0 ||
128 			ucstrcmp(alert->getMessageUC(), _UC("ModelParsed")) == 0 ||
129 			ucstrcmp(alert->getMessageUC(), _UC("ModelParseCanceled")) == 0)
130 		{
131 			updateStep();
132 			updateNumSteps();
133 		}
134 	}
135 }
136 
create(LDViewWindow * parent)137 void ToolbarStrip::create(LDViewWindow *parent)
138 {
139 	m_ldviewWindow = parent;
140 	m_prefs = m_ldviewWindow->getModelWindow()->getPrefs();
141 	m_prefs->retain();
142 	::CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_TOOLBAR),
143 		parent->getHWindow(), staticDialogProc, (LPARAM)this);
144 }
145 
show(void)146 void ToolbarStrip::show(void)
147 {
148 	::ShowWindow(hWindow, SW_SHOW);
149 }
150 
hide(void)151 void ToolbarStrip::hide(void)
152 {
153 	::ShowWindow(hWindow, SW_HIDE);
154 }
155 
updateMenus(void)156 void ToolbarStrip::updateMenus(void)
157 {
158 	HMENU hMenu = NULL;
159 
160 	hMenu = GetMenu(GetParent(hWindow));
161 	if (hMenu != NULL)
162 	{
163 		updateMenuImages(hMenu, true);
164 		updateMenuImages(m_hMainToolbarMenu);
165 		updateMenuImages(m_hContextMenu);
166 		updateMenuImages(m_hPrimitivesMenu);
167 	}
168 }
169 
initToolbar(HWND hToolbar,TbButtonInfoVector & infos,HIMAGELIST hImageList)170 void ToolbarStrip::initToolbar(
171 	HWND hToolbar,
172 	TbButtonInfoVector &infos,
173 	HIMAGELIST hImageList)
174 {
175 	TBBUTTON *buttons;
176 	UCCHAR buttonTitle[128];
177 	int i;
178 	int count;
179 
180 #ifndef TC_NO_UNICODE
181 	SendMessage(hToolbar, TB_SETUNICODEFORMAT, (WPARAM)TRUE, 0);
182 #endif // !TC_NO_UNICODE
183 	SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0,
184 		TBSTYLE_EX_DRAWDDARROWS | WS_EX_TRANSPARENT);
185 	memset(buttonTitle, 0, sizeof(buttonTitle));
186 	SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
187 	SendMessage(hToolbar, TB_SETBUTTONWIDTH, 0, MAKELONG(m_buttonWidth, m_buttonWidth));
188 	SendMessage(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
189 	m_stdBitmapStartId = m_tbBitmapStartId = 0;
190 	SendMessage(hToolbar, TB_ADDSTRING, 0, (LPARAM)buttonTitle);
191 	count = (int)infos.size();
192 	buttons = new TBBUTTON[count];
193 	for (i = 0; i < count; i++)
194 	{
195 		fillTbButton(buttons[i], infos[i]);
196 		buttons[i].iBitmap += infos[i].getSelection();
197 	}
198 	SendMessage(hToolbar, TB_ADDBUTTONS, count, (LPARAM)buttons);
199 	if (!CUIThemes::isThemeActive() ||
200 		((CUIThemes::getThemeAppProperties() & STAP_ALLOW_CONTROLS) == 0))
201 	{
202 		SendMessage(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(m_buttonWidth, m_buttonHeight));
203 	}
204 	sizeToolbar(hToolbar, count);
205 	delete[] buttons;
206 	SendMessage(hToolbar, TB_SETHOTITEM, (WPARAM)-1, 0);
207 	ShowWindow(hToolbar, SW_SHOW);
208 }
209 
sizeToolbar(HWND hToolbar,int count)210 void ToolbarStrip::sizeToolbar(HWND hToolbar, int count)
211 {
212 	RECT buttonRect;
213 	RECT rect;
214 	int lwidth;
215 	int lheight;
216 
217 	GetWindowRect(hToolbar, &rect);
218 	screenToClient(hWindow, &rect);
219 	if (!SendMessage(hToolbar, TB_GETITEMRECT, count - 1, (LPARAM)&buttonRect))
220 	{
221 		buttonRect = rect;
222 		buttonRect.left -= rect.left;
223 		buttonRect.right -= rect.right;
224 	}
225 	lwidth = buttonRect.right;
226 	lheight = buttonRect.bottom - buttonRect.top;
227 	MoveWindow(hToolbar, rect.left, rect.top, lwidth, lheight, FALSE);
228 }
229 
fillTbButton(TBBUTTON & button,const TbButtonInfo & buttonInfo)230 void ToolbarStrip::fillTbButton(
231 	TBBUTTON &button,
232 	const TbButtonInfo &buttonInfo)
233 {
234 	button.iBitmap = buttonInfo.getBmpIndex();
235 	button.idCommand = buttonInfo.getCommandId();
236 	button.fsState = buttonInfo.getState();
237 	button.fsStyle = buttonInfo.getStyle();
238 	button.dwData = (DWORD_PTR)this;
239 	button.iString = -1;
240 }
241 
loadMainToolbarMenus(void)242 void ToolbarStrip::loadMainToolbarMenus(void)
243 {
244 	m_hMainToolbarMenu = LoadMenu(getLanguageModule(),
245 		MAKEINTRESOURCE(IDR_TOOLBAR_MENU));
246 	m_hContextMenu = GetSubMenu(m_hMainToolbarMenu, 0);
247 	m_hWireframeMenu = GetSubMenu(m_hMainToolbarMenu, 1);
248 	m_hEdgesMenu = GetSubMenu(m_hMainToolbarMenu, 2);
249 	m_hPrimitivesMenu = GetSubMenu(m_hMainToolbarMenu, 3);
250 	m_hLightingMenu = GetSubMenu(m_hMainToolbarMenu, 4);
251 	m_hBFCMenu = GetSubMenu(m_hMainToolbarMenu, 5);
252 }
253 
initMainToolbar(void)254 void ToolbarStrip::initMainToolbar(void)
255 {
256 	DWORD style = GetWindowLong(m_hToolbar, GWL_STYLE);
257 
258 	loadMainToolbarMenus();
259 	populateMainTbButtonInfos();
260 	SendMessage(m_hToolbar, TB_SETSTYLE, 0, style | CCS_ADJUSTABLE);
261 	fillMainToolbar();
262 }
263 
fillMainToolbar(void)264 void ToolbarStrip::fillMainToolbar(void)
265 {
266 	size_t i;
267 	LongVector mainButtonIDs;
268 	LongSizeTMap mainButtonsMap;
269 	TbButtonInfoVector buttonInfos;
270 
271 	for (i = 0; i < m_mainButtonInfos.size(); i++)
272 	{
273 		long commandID = m_mainButtonInfos[i].getCommandId();
274 
275 		if (i < NUM_DEFAULT_TB_BUTTONS)
276 		{
277 			mainButtonIDs.push_back(commandID);
278 		}
279 		mainButtonsMap[commandID] = i;
280 	}
281 	mainButtonIDs = TCUserDefaults::longVectorForKey(MAIN_TOOLBAR_IDS_KEY,
282 		mainButtonIDs, false);
283 	for (i = 0; i < mainButtonIDs.size(); i++)
284 	{
285 		int commandId = mainButtonIDs[i];
286 
287 		if (commandId > 0)
288 		{
289 			LongSizeTMap::const_iterator it = mainButtonsMap.find(commandId);
290 
291 			if (it != mainButtonsMap.end())
292 			{
293 				buttonInfos.push_back(m_mainButtonInfos[it->second]);
294 			}
295 		}
296 		else
297 		{
298 			addTbSeparatorInfo(buttonInfos);
299 		}
300 	}
301 	initToolbar(m_hToolbar, buttonInfos, m_imageLists.front());
302 }
303 
initStepToolbar(void)304 void ToolbarStrip::initStepToolbar(void)
305 {
306 	populateStepTbButtonInfos();
307 	initToolbar(m_hStepToolbar, m_stepButtonInfos, m_imageLists.back());
308 }
309 
autoSize(void)310 void ToolbarStrip::autoSize(void)
311 {
312 	RECT rect;
313 	RECT parentRect;
314 
315 	GetWindowRect(hWindow, &rect);
316 	GetClientRect(m_ldviewWindow->getHWindow(), &parentRect);
317 	screenToClient(m_ldviewWindow->getHWindow(), &rect);
318 	MoveWindow(hWindow, rect.left, rect.top, parentRect.right - parentRect.left,
319 		m_stripHeight, TRUE);
320 }
321 
initLayout(void)322 void ToolbarStrip::initLayout(void)
323 {
324 	RECT tbRect;
325 	RECT rect;
326 	int delta;
327 	int left;
328 	//int right;
329 	int lmaxHeight;
330 	size_t i;
331 	int show = m_showSteps ? SW_SHOW : SW_HIDE;
332 
333 	ShowWindow(m_hToolbar, m_showMain ? SW_SHOW : SW_HIDE);
334 	ShowWindow(m_hStepLabel, show);
335 	ShowWindow(m_hNumStepsLabel, show);
336 	GetWindowRect(m_hToolbar, &tbRect);
337 	screenToClient(hWindow, &tbRect);
338 	GetWindowRect(m_hStepLabel, &rect);
339 	screenToClient(hWindow, &rect);
340 	if (m_showMain)
341 	{
342 		delta = tbRect.right + 16 - rect.left;
343 	}
344 	else
345 	{
346 		delta = 4 - rect.left;
347 	}
348 	lmaxHeight = tbRect.bottom - tbRect.top;
349 	for (i = 1; i < m_controls.size(); i++)
350 	{
351 		int lheight;
352 
353 		ShowWindow(m_controls[i], show);
354 		GetWindowRect(m_controls[i], &rect);
355 		screenToClient(hWindow, &rect);
356 		lheight = rect.bottom - rect.top;
357 		MoveWindow(m_controls[i], rect.left + delta, rect.top,
358 			rect.right - rect.left, lheight, FALSE);
359 		if (lheight > lmaxHeight)
360 		{
361 			lmaxHeight = lheight;
362 		}
363 	}
364 	m_stripHeight = lmaxHeight + 4;
365 	lmaxHeight += 4;
366 	left = 4;
367 	for (i = 0; i < m_controls.size(); i++)
368 	{
369 		int lheight;
370 
371 		GetWindowRect(m_controls[i], &rect);
372 		screenToClient(hWindow, &rect);
373 		lheight = rect.bottom - rect.top;
374 		MoveWindow(m_controls[i], left, (lmaxHeight - lheight) / 2,
375 			rect.right - rect.left, lheight, TRUE);
376 		left += rect.right - rect.left + 2;
377 	}
378 	autoSize();
379 	RedrawWindow(hWindow, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
380 }
381 
stepChanged(void)382 void ToolbarStrip::stepChanged(void)
383 {
384 	ModelWindow *modelWindow = m_ldviewWindow->getModelWindow();
385 	LDrawModelViewer *modelViewer = modelWindow->getModelViewer();
386 
387 	if (modelViewer)
388 	{
389 		int step;
390 
391 		if (windowGetValue(IDC_STEP, step))
392 		{
393 			m_step = m_ldviewWindow->setStep(step);
394 			updateStep();
395 		}
396 	}
397 	else
398 	{
399 		updateStep();
400 	}
401 }
402 
enableToolbarButton(HWND hToolbar,UINT buttonId,bool enable)403 void ToolbarStrip::enableToolbarButton(
404 	HWND hToolbar,
405 	UINT buttonId,
406 	bool enable)
407 {
408 	BYTE state = (BYTE)SendMessage(hToolbar, TB_GETSTATE, (WPARAM)buttonId, 0);
409 
410 	if (state == -1)
411 	{
412 		state = 0;
413 	}
414 	if (enable)
415 	{
416 		state |= TBSTATE_ENABLED;
417 	}
418 	else
419 	{
420 		state &= ~TBSTATE_ENABLED;
421 	}
422 	SendMessage(hToolbar, TB_SETSTATE, (WPARAM)buttonId, MAKELONG(state, 0));
423 }
424 
updateStep(void)425 void ToolbarStrip::updateStep(void)
426 {
427 	LDrawModelViewer *modelViewer =
428 		m_ldviewWindow->getModelWindow()->getModelViewer();
429 	bool prevEnabled = false;
430 	bool nextEnabled = false;
431 
432 	if (modelViewer)
433 	{
434 		m_step = modelViewer->getStep();
435 	}
436 	else
437 	{
438 		m_step = 0;
439 	}
440 	if (m_step > 0)
441 	{
442 		UCCHAR buf[1024];
443 
444 		sucprintf(buf, COUNT_OF(buf), _UC("%d"), m_step);
445 		windowSetText(IDC_STEP, buf);
446 		if (GetFocus() == m_hStepField)
447 		{
448 			SendMessage(m_hStepField, EM_SETSEL, 0, (LPARAM)-1);
449 		}
450 		prevEnabled = m_step > 1;
451 		nextEnabled = m_step < modelViewer->getNumSteps();
452 	}
453 	else
454 	{
455 		windowSetText(IDC_STEP, _UC("--"));
456 	}
457 	enableToolbarButton(m_hStepToolbar, ID_FIRST_STEP, prevEnabled);
458 	enableToolbarButton(m_hStepToolbar, ID_PREV_STEP, prevEnabled);
459 	enableToolbarButton(m_hStepToolbar, ID_NEXT_STEP, nextEnabled);
460 	enableToolbarButton(m_hStepToolbar, ID_LAST_STEP, nextEnabled);
461 	RedrawWindow(m_hStepField, NULL, NULL, RDW_ERASE | RDW_INVALIDATE |
462 		RDW_ERASENOW | RDW_UPDATENOW);
463 	RedrawWindow(m_hStepToolbar, NULL, NULL, RDW_ERASE | RDW_INVALIDATE |
464 		RDW_ERASENOW | RDW_UPDATENOW);
465 }
466 
doTimer(UINT_PTR timerID)467 LRESULT ToolbarStrip::doTimer(UINT_PTR timerID)
468 {
469 	switch (timerID)
470 	{
471 	case STEP_COUNT_CHANGED_TIMER:
472 		stepCountChanged();
473 		break;
474 	}
475 	return 0;
476 }
477 
stepCountChanged(void)478 void ToolbarStrip::stepCountChanged(void)
479 {
480 	KillTimer(hWindow, STEP_COUNT_CHANGED_TIMER);
481 	UCCHAR buf[1024] = _UC("");
482 
483 	if (m_numSteps > 0)
484 	{
485 		sucprintf(buf, COUNT_OF(buf), m_numStepsFormat.c_str(), m_numSteps);
486 	}
487 	SIZE size;
488 	HDC hNumStepsLabelDC = ::GetDC(m_hNumStepsLabel);
489 	HANDLE hFont = (HANDLE)::SendMessage(m_hNumStepsLabel, WM_GETFONT, 0, 0);
490 	HANDLE hOldFont = ::SelectObject(hNumStepsLabelDC, hFont);
491 	CUIWindow::getTextExtentPoint32UC(hNumStepsLabelDC, buf, (int)ucstrlen(buf), &size);
492 	::SelectObject(hNumStepsLabelDC, hOldFont);
493 	::ReleaseDC(m_hNumStepsLabel, hNumStepsLabelDC);
494 	RECT rect;
495 	::GetWindowRect(m_hNumStepsLabel, &rect);
496 	CUIWindow::screenToClient(hWindow, &rect);
497 	::MoveWindow(m_hNumStepsLabel, rect.left, rect.top, size.cx + 4,
498 		rect.bottom - rect.top, FALSE);
499 	windowSetText(IDC_NUM_STEPS, buf);
500 	initLayout();
501 }
502 
updateNumSteps(void)503 void ToolbarStrip::updateNumSteps(void)
504 {
505 	LDrawModelViewer *modelViewer =
506 		m_ldviewWindow->getModelWindow()->getModelViewer();
507 
508 	if (modelViewer)
509 	{
510 		m_numSteps = modelViewer->getNumSteps();
511 	}
512 	else
513 	{
514 		m_numSteps = 0;
515 	}
516 	::SetTimer(hWindow, STEP_COUNT_CHANGED_TIMER, 0, NULL);
517 }
518 
519 #ifdef USE_GDIPLUS
updateMenuImages(HMENU hMenu,bool topMenu)520 void ToolbarStrip::updateMenuImages(HMENU hMenu, bool topMenu /*= false*/)
521 {
522 	bool themed = m_ldviewWindow->isVisualStyleEnabled() ||
523 		TCUserDefaults::boolForKey(FORCE_THEMED_MENUS_KEY, false, false);
524 
525 	//if (m_hGdiPlus == NULL)
526 	//{
527 	//	return;
528 	//}
529 	int count = GetMenuItemCount(hMenu);
530 
531 	for (int i = 0; i < count; i++)
532 	{
533 		MENUITEMINFOUC mii;
534 		UCCHAR stringBuf[1024];
535 		HBITMAP hOldBitmap = NULL;
536 
537 		memset(&mii, 0, sizeof(mii));
538 		mii.cbSize = sizeof(mii);
539 		mii.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_BITMAP;
540 		if ((!themed || !have32BitBmps) && !topMenu)
541 		{
542 			mii.fMask |= MIIM_STRING;
543 			mii.dwTypeData = stringBuf;
544 			mii.cch = COUNT_OF(stringBuf);
545 		}
546 		GetMenuItemInfoUC(hMenu, i, TRUE, &mii);
547 		hOldBitmap = mii.hbmpItem;
548 		if ((!themed || !have32BitBmps) && !topMenu)
549 		{
550 			// Window sucks.  When themes are disabled, menu item icons encroach
551 			// into the beginning of the menu item text.  So, to combat this, we
552 			// need to add a space to the beginning of all menu items to allow
553 			// space for the icon.  Since the app's main menu doesn't have any
554 			// icons, we'll skip the spaces on that.
555 			ucstring menuString(_UC(" "));
556 			MENUITEMINFOUC mii2 = mii;
557 
558 			menuString += mii.dwTypeData;
559 			mii2.dwTypeData = &menuString[0];
560 			mii2.fMask = MIIM_STRING;
561 			SetMenuItemInfoUC(hMenu, i, TRUE, &mii2);
562 		}
563 		if (mii.hSubMenu)
564 		{
565 			updateMenuImages(mii.hSubMenu);
566 		}
567 		else
568 		{
569 			ImageIndexMap::const_iterator it = m_imagesMap.find(mii.wID);
570 
571 			if (it != m_imagesMap.end())
572 			{
573 				HBITMAP hMenuBitmap = NULL;
574 
575 				if (CUIScaler::use32bit())
576 				{
577 					double scaleFactor = m_scaleFactor;
578 					// Menu sizes don't scale exactly with screen scale
579 					// factor, and we want the icon to be as big as possible
580 					// without being too big.
581 					if (scaleFactor > 1.0 && scaleFactor <= 1.25)
582 					{
583 						// For some reason, the icon gets squished by Windows
584 						// if we don't do this. I have no idea why.
585 						scaleFactor = 1.0;
586 					}
587 					hMenuBitmap = TCImage::loadBmpFromPngResource(NULL,
588 						translateCommandId(mii.wID), scaleFactor, true, 1);
589 				}
590 				else
591 				{
592 					HIMAGELIST hImageList = m_imageLists[it->second.first];
593 					HICON hIcon = ImageList_GetIcon(hImageList,
594 						it->second.second, ILD_TRANSPARENT);
595 					Gdiplus::GpBitmap *pBitmap;
596 					if (have32BitBmps)
597 					{
598 						if (GdipCreateBitmapFromHICON(hIcon, &pBitmap) ==
599 							Gdiplus::Ok)
600 						{
601 							if (GdipCreateHBITMAPFromBitmap(pBitmap,
602 								&hMenuBitmap, 0) != Gdiplus::Ok)
603 							{
604 								hMenuBitmap = NULL;
605 							}
606 							GdipDisposeImage(pBitmap);
607 						}
608 					}
609 					else if (hIcon != NULL)
610 					{
611 						ICONINFO ii;
612 						BITMAP bi;
613 
614 						if (::GetIconInfo(hIcon, &ii) &&
615 							::GetObject(ii.hbmColor, sizeof(bi), &bi))
616 						{
617 							HWND hParentWnd = ::GetParent(hWindow);
618 							HDC hdcWin = ::GetDC(hParentWnd);
619 							HDC hCompatDC = ::CreateCompatibleDC(hdcWin);
620 							RECT rect;
621 
622 							rect.left = rect.top = 0;
623 							// Windows has an off by one error, where it
624 							// clobbers the right pixel of menu images.
625 							rect.right = bi.bmWidth + 1;
626 							rect.bottom = bi.bmHeight;
627 							hMenuBitmap = ::CreateCompatibleBitmap(hdcWin,
628 								bi.bmWidth + 1, bi.bmHeight);
629 							HBITMAP hOldBitmap =
630 								(HBITMAP)::SelectObject(hCompatDC, hMenuBitmap);
631 							::FillRect(hCompatDC, &rect,
632 								::GetSysColorBrush(COLOR_MENU));
633 							::DrawIconEx(hCompatDC, 0, 0, hIcon, bi.bmWidth,
634 								bi.bmHeight, 0, NULL, DI_NORMAL);
635 							::SelectObject(hCompatDC, hOldBitmap);
636 							::ReleaseDC(hParentWnd, hdcWin);
637 							::ReleaseDC(NULL, hCompatDC);
638 						}
639 					}
640 					if (hIcon != NULL)
641 					{
642 						::DestroyIcon(hIcon);
643 					}
644 				}
645 				if (hMenuBitmap != NULL)
646 				{
647 					mii.fMask = MIIM_BITMAP;
648 					mii.hbmpItem = hMenuBitmap;
649 					SetMenuItemInfoUC(hMenu, i, TRUE, &mii);
650 					if (hOldBitmap != NULL)
651 					{
652 						DeleteObject(hOldBitmap);
653 					}
654 				}
655 			}
656 		}
657 	}
658 }
659 #else // USE_GDIPLUS
updateMenuImages(HMENU,bool)660 void ToolbarStrip::updateMenuImages(HMENU, bool)
661 {
662 }
663 #endif // USE_GDIPLUS
664 
doInitDialog(HWND)665 BOOL ToolbarStrip::doInitDialog(HWND /*hKbControl*/)
666 {
667 	m_hToolbar = GetDlgItem(hWindow, IDC_TOOLBAR);
668 	m_hStepLabel = GetDlgItem(hWindow, IDC_STEP_LABEL);
669 	m_hStepField = GetDlgItem(hWindow, IDC_STEP);
670 	m_hNumStepsLabel = GetDlgItem(hWindow, IDC_NUM_STEPS);
671 	m_hStepToolbar = GetDlgItem(hWindow, IDC_STEP_TOOLBAR);
672 	m_controls.push_back(m_hToolbar);
673 	m_controls.push_back(m_hStepLabel);
674 	m_controls.push_back(m_hStepField);
675 	m_controls.push_back(m_hNumStepsLabel);
676 	m_controls.push_back(m_hStepToolbar);
677 
678 #ifdef USE_GDIPLUS
679 #pragma warning(push)
680 #pragma warning(disable:4996)
681 	if ((GetVersion() & 0xFF) >= 6)
682 	{
683 		// We use GDI+ for creation of 32-bit color menu item bitmaps.  These
684 		// are only supported in menus in Vista and beyond, so don't even try
685 		// to load it in earlier OSes.
686 		m_hGdiPlus = LoadLibrary(_UC("gdiplus.dll"));
687 	}
688 #pragma warning(pop)
689 	ULONG_PTR gdiplusToken = 0;
690 
691 	if (m_hGdiPlus != NULL)
692 	{
693 		bool started = false;
694 
695 		GdiplusStartup = (PFNGDIPLUSSTARTUP)GetProcAddress(m_hGdiPlus,
696 			"GdiplusStartup");
697 		GdiplusShutdown = (PFNGDIPLUSSHUTDOWN)GetProcAddress(m_hGdiPlus,
698 			"GdiplusShutdown");
699 		GdipCreateBitmapFromHICON =
700 			(PFNGDIPCREATEBITMAPFROMHICON)GetProcAddress(m_hGdiPlus,
701 			"GdipCreateBitmapFromHICON");
702 		GdipCreateHBITMAPFromBitmap =
703 			(PFNGDIPCREATEHBITMAPFROMBITMAP)GetProcAddress(m_hGdiPlus,
704 			"GdipCreateHBITMAPFromBitmap");
705 		GdipDisposeImage = (PFNGDIPDISPOSEIMAGE)GetProcAddress(m_hGdiPlus,
706 			"GdipDisposeImage");
707 
708 		if (GdiplusStartup != NULL &&
709 			GdiplusShutdown != NULL &&
710 			GdipCreateBitmapFromHICON != NULL &&
711 			GdipCreateHBITMAPFromBitmap != NULL &&
712 			GdipDisposeImage != NULL)
713 		{
714 			Gdiplus::GdiplusStartupInput gdiplusStartupInput;
715 
716 			// Initialize GDI+.
717 			if (GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) ==
718 				Gdiplus::Ok)
719 			{
720 				started = true;
721 				have32BitBmps = true;
722 			}
723 		}
724 		if (!started)
725 		{
726 			FreeLibrary(m_hGdiPlus);
727 			m_hGdiPlus = NULL;
728 		}
729 	}
730 #endif // USE_GDIPLUS
731 
732 	windowGetText(IDC_NUM_STEPS, m_numStepsFormat);
733 	windowSetText(IDC_NUM_STEPS, _UC(""));
734 	m_scaleFactor = m_ldviewWindow->getScaleFactor();
735 	if (m_scaleFactor > 1.0)
736 	{
737 		m_imageSize = (int)(16.0 * m_scaleFactor);
738 		m_buttonWidth = (int)(22.0 * m_scaleFactor);
739 		m_buttonHeight = (int)(24.0 * m_scaleFactor);
740 	}
741 	else
742 	{
743 		m_imageSize = 16;
744 		m_buttonWidth = 22;
745 		m_buttonHeight = 24;
746 	}
747 	initMainToolbar();
748 	initStepToolbar();
749 	checksReflect();
750 	updateMenus();
751 	initLayout();
752 	updateStep();
753 	updateNumSteps();
754 #ifdef USE_GDIPLUS
755 	if (m_hGdiPlus != NULL)
756 	{
757 		GdiplusShutdown(gdiplusToken);
758 	}
759 #endif // USE_GDIPLUS
760 	return TRUE;
761 }
762 
doTextFieldChange(int controlId,HWND control)763 LRESULT ToolbarStrip::doTextFieldChange(int controlId, HWND control)
764 {
765 	return CUIDialog::doTextFieldChange(controlId, control);
766 }
767 
doCommand(int notifyCode,int commandId,HWND control)768 LRESULT ToolbarStrip::doCommand(
769 	int notifyCode,
770 	int commandId,
771 	HWND control)
772 {
773 	switch (commandId)
774 	{
775 	case IDOK:
776 	case EN_KILLFOCUS:
777 		stepChanged();
778 		return 0;
779 	case ID_EDIT_PREFERENCES:
780 	case ID_FILE_OPEN:
781 	case ID_FILE_SAVE:
782 	case ID_FILE_RELOAD:
783 	case ID_VIEW_RESET:
784 	case ID_VIEW_DEFAULT:
785 	case ID_VIEW_FRONT:
786 	case ID_VIEW_BACK:
787 	case ID_VIEW_LEFT:
788 	case ID_VIEW_RIGHT:
789 	case ID_VIEW_TOP:
790 	case ID_VIEW_BOTTOM:
791 	case ID_VIEW_SPECIFYLATLON:
792 	case ID_VIEW_ISO:
793 	case ID_VIEW_SAVE_DEFAULT:
794 	case ID_NEXT_STEP:
795 	case ID_PREV_STEP:
796 	case ID_FIRST_STEP:
797 	case ID_LAST_STEP:
798 	case ID_TOOLS_ERRORS:
799 	case ID_VIEW_FULLSCREEN:
800 	case ID_VIEW_ZOOMTOFIT:
801 	case ID_HELP_CONTENTS:
802 	case ID_TOOLS_MODELTREE:
803 	case ID_TOOLS_BOUNDINGBOX:
804 	case ID_VIEW_ALWAYSONTOP:
805 	case ID_FILE_EXPORT:
806 	case ID_FILE_PRINT:
807 	case ID_VIEW_EXAMINE_LAT_LONG:
808 	case ID_TOOLS_PARTSLIST:
809 	case ID_TOOLS_MPD:
810 	case ID_TOOLS_POV_CAMERA:
811 	case ID_VIEW_RIGHTSIDEUP:
812 		// Forward all these messages to LDViewWindow.
813 		return SendMessage(m_ldviewWindow->getHWindow(), WM_COMMAND,
814 			MAKEWPARAM(commandId, notifyCode), (LPARAM)control);
815 	case IDC_WIREFRAME:
816 		doWireframe();
817 		break;
818 	case IDC_SEAMS:
819 		doSeams();
820 		break;
821 	case IDC_HIGHLIGHTS:
822 		doEdges();
823 		break;
824 	case IDC_PRIMITIVE_SUBSTITUTION:
825 		doPrimitiveSubstitution();
826 		break;
827 	case IDC_LIGHTING:
828 		doLighting();
829 		break;
830 	case IDC_BFC:
831 		doBfc();
832 		break;
833 	case IDC_SHOW_AXES:
834 		doShowAxes();
835 		break;
836 	case IDC_RANDOM_COLORS:
837 		doRandomColors();
838 		break;
839 	case IDC_ALL_CONDITIONAL:
840 		doAllConditionals();
841 		break;
842 	case IDC_CONDITIONAL_CONTROLS:
843 		doConditionalControls();
844 		break;
845 	case IDC_FLAT_SHADING:
846 		doFlatShading();
847 		break;
848 	case IDC_CUTAWAY:
849 		doCutaway();
850 		break;
851 	case IDC_STUD_QUALITY:
852 		doStudQuality();
853 		break;
854 	case IDC_PART_BOUNDING_BOXES:
855 		doPartBoundingBoxes();
856 		break;
857 	case IDC_SMOOTH_CURVES:
858 		doSmoothCurves();
859 		break;
860 	case IDC_TRANS_DEFAULT_COLOR:
861 		doTransDefaultColor();
862 		break;
863 	case ID_WIREFRAME_FOG:
864 		doFog();
865 		break;
866 	case ID_WIREFRAME_REMOVEHIDDENLINES:
867 		doRemoveHiddenLines();
868 		break;
869 	case ID_EDGES_SHOWEDGESONLY:
870 		doShowEdgesOnly();
871 		break;
872 	case ID_EDGES_CONDITIONALLINES:
873 		doConditionalLines();
874 		break;
875 	case ID_EDGES_HIGHQUALITY:
876 		doHighQualityEdges();
877 		break;
878 	case ID_EDGES_ALWAYSBLACK:
879 		doAlwaysBlack();
880 		break;
881 	case ID_PRIMITIVES_TEXTURESTUDS:
882 		doTextureStuds();
883 		break;
884 	case ID_PRIMITIVES_TEXMAPS:
885 		doTexmaps();
886 		break;
887 	case ID_LIGHTING_HIGHQUALITY:
888 		doQualityLighting();
889 		break;
890 	case ID_LIGHTING_SUBDUED:
891 		doSubduedLighting();
892 		break;
893 	case ID_LIGHTING_SPECULARHIGHLIGHT:
894 		doSpecularHighlight();
895 		break;
896 	case ID_LIGHTING_ALTERNATESETUP:
897 		doAlternateLighting();
898 		break;
899 	case ID_LIGHTING_DRAWDATS:
900 		doDrawLightDats();
901 		break;
902 	case ID_LIGHTING_OPTIONALMAIN:
903 		doOptionalStandardLight();
904 		break;
905 	case ID_BFC_REDBACKFACES:
906 		doRedBackFaces();
907 		break;
908 	case ID_BFC_GREENFRONTFACES:
909 		doGreenFrontFaces();
910 		break;
911 	case ID_BFC_BLUENEUTRALFACES:
912 		doBlueNeutralFaces();
913 		break;
914 	case ID_TBCONTEXT_CUSTOMIZE:
915 		doCustomizeMainToolbar();
916 		break;
917 	case ID_TBCONTEXT_MAIN:
918 		doMainToolbar();
919 		break;
920 	case ID_TBCONTEXT_STEPS:
921 		doStepsToolbar();
922 		break;
923 	case ID_VIEW_EXAMINE:
924 		doViewMode();
925 		break;
926 	default:
927 		return CUIDialog::doCommand(notifyCode, commandId, control);
928 	}
929 	return 0;
930 }
931 
translateCommandId(int commandId)932 int ToolbarStrip::translateCommandId(int commandId)
933 {
934 	IntIntMap::const_iterator it = m_commandMap.find(commandId);
935 	if (it != m_commandMap.end())
936 	{
937 		return it->second;
938 	}
939 	return commandId;
940 }
941 
addToImageList(int commandId)942 int ToolbarStrip::addToImageList(int commandId)
943 {
944 	int newCommandId = translateCommandId(commandId);
945 	TCImage *image;
946 	static bool disableHighRes = false;
947 
948 //#ifdef _DEBUG
949 //	// Make sure scaling works, but also make sure high-res versions work.
950 //	disableHighRes = !disableHighRes;
951 //#endif
952 	image = TCImage::createFromResource(NULL, newCommandId, 4, true,
953 		disableHighRes ? 1.0 : m_scaleFactor);
954 	if (image != NULL)
955 	{
956 		SIZE imageSize = { m_imageSize, m_imageSize };
957 		int imageIndex = addImageToImageList(m_imageLists.back(), image, imageSize);
958 		image->release();
959 		if (imageIndex >= 0)
960 		{
961 			m_imagesMap[commandId].first = m_imageLists.size() - 1;
962 			m_imagesMap[commandId].second = imageIndex;
963 		}
964 		return imageIndex;
965 	}
966 	return -1;
967 }
968 
addTbButtonInfo(TbButtonInfoVector & infos,CUCSTR tooltipText,int commandId,BYTE style,BYTE state)969 void ToolbarStrip::addTbButtonInfo(
970 	TbButtonInfoVector &infos,
971 	CUCSTR tooltipText,
972 	int commandId,
973 	BYTE style,
974 	BYTE state)
975 {
976 	infos.resize(infos.size() + 1);
977 	TbButtonInfo &buttonInfo = infos.back();
978 	buttonInfo.setTooltipText(tooltipText);
979 	buttonInfo.setCommandId(commandId);
980 	buttonInfo.setBmpIndex(addToImageList(commandId));
981 	buttonInfo.setStyle(style);
982 	buttonInfo.setState(state);
983 }
984 
addTbCheckButtonInfo(TbButtonInfoVector & infos,CUCSTR tooltipText,int commandId,bool checked,BYTE style,BYTE state)985 void ToolbarStrip::addTbCheckButtonInfo(
986 	TbButtonInfoVector &infos,
987 	CUCSTR tooltipText,
988 	int commandId,
989 	bool checked,
990 	BYTE style,
991 	BYTE state)
992 {
993 	state &= ~TBSTATE_CHECKED;
994 	if (checked)
995 	{
996 		state |= TBSTATE_CHECKED;
997 	}
998 	addTbButtonInfo(infos, tooltipText, commandId, style, state);
999 }
1000 
addTbStateButtonInfo(TbButtonInfoVector & infos,CUCSTR tooltipText,IntVector commandIds,int selection,BYTE style,BYTE state)1001 void ToolbarStrip::addTbStateButtonInfo(
1002 	TbButtonInfoVector &infos,
1003 	CUCSTR tooltipText,
1004 	IntVector commandIds,
1005 	int selection,
1006 	BYTE style /*= TBSTYLE_BUTTON*/,
1007 	BYTE state /*= TBSTATE_ENABLED*/)
1008 {
1009 	addTbButtonInfo(infos, tooltipText, commandIds.front(), style,
1010 		state | TBSTATE_CHECKED);
1011 	TbButtonInfo &buttonInfo = infos.back();
1012 	buttonInfo.setSelection(selection);
1013 	for (size_t i = 1; i < commandIds.size(); i++)
1014 	{
1015 		buttonInfo.addCommandId(commandIds[i]);
1016 		addToImageList(commandIds[i]);
1017 	}
1018 }
1019 
addTbSeparatorInfo(TbButtonInfoVector & infos)1020 void ToolbarStrip::addTbSeparatorInfo(TbButtonInfoVector &infos)
1021 {
1022 	infos.resize(infos.size() + 1);
1023 	TbButtonInfo &buttonInfo = infos.back();
1024 
1025 	buttonInfo.setStyle(TBSTYLE_SEP);
1026 }
1027 
populateStepTbButtonInfos(void)1028 void ToolbarStrip::populateStepTbButtonInfos(void)
1029 {
1030 	if (m_stepButtonInfos.size() == 0)
1031 	{
1032 		m_imageLists.push_back(ImageList_Create(m_imageSize, m_imageSize,
1033 			CUIScaler::imageListCreateFlags(), 0, 10));
1034 		addTbButtonInfo(m_stepButtonInfos,
1035 			ls(_UC("FirstStep")), ID_FIRST_STEP);
1036 		addTbButtonInfo(m_stepButtonInfos,
1037 			ls(_UC("PrevStep")), ID_PREV_STEP);
1038 		addTbButtonInfo(m_stepButtonInfos,
1039 			ls(_UC("NextStep")), ID_NEXT_STEP);
1040 		addTbButtonInfo(m_stepButtonInfos,
1041 			ls(_UC("LastStep")), ID_LAST_STEP);
1042 	}
1043 }
1044 
syncViewMode(void)1045 void ToolbarStrip::syncViewMode(void)
1046 {
1047 	m_viewMode =
1048 		(LDInputHandler::ViewMode)TCUserDefaults::longForKey(VIEW_MODE_KEY, 0,
1049 		false);
1050 }
1051 
populateMainTbButtonInfos(void)1052 void ToolbarStrip::populateMainTbButtonInfos(void)
1053 {
1054 	if (m_mainButtonInfos.size() == 0)
1055 	{
1056 		m_imageLists.push_back(ImageList_Create(m_imageSize, m_imageSize,
1057 			CUIScaler::imageListCreateFlags(), 0, 100));
1058 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("OpenFile")),
1059 			ID_FILE_OPEN);
1060 		addTbButtonInfo(m_mainButtonInfos,
1061 			ls(_UC("SaveSnapshot")), ID_FILE_SAVE);
1062 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("Reload")),
1063 			ID_FILE_RELOAD);
1064 		addTbSeparatorInfo(m_mainButtonInfos);
1065 		m_drawWireframe = m_prefs->getDrawWireframe();
1066 		m_seams = m_prefs->getUseSeams() != 0;
1067 		m_edges = m_prefs->getShowsHighlightLines();
1068 		m_primitiveSubstitution = m_prefs->getAllowPrimitiveSubstitution();
1069 		m_lighting = m_prefs->getUseLighting();
1070 		m_bfc = m_prefs->getBfc();
1071 		m_showAxes = m_prefs->getShowAxes();
1072 		m_randomColors = m_prefs->getRandomColors();
1073 		m_allConditionals = m_prefs->getShowAllConditionalLines();
1074 		m_conditionalControls = m_prefs->getShowConditionalControlPoints();
1075 		m_flat = m_prefs->getUseFlatShading();
1076 		m_wireframeCutaway = m_prefs->getCutawayMode() == LDVCutawayWireframe;
1077 		m_lowStuds = !m_prefs->getQualityStuds();
1078 		m_partBBoxes = m_prefs->getBoundingBoxesOnly();
1079 		m_smoothCurves = m_prefs->getPerformSmoothing();
1080 		m_transDefaultColor = m_prefs->getTransDefaultColor();
1081 		m_texmaps = m_prefs->getTexmaps();
1082 		m_examineLatLong = TCUserDefaults::longForKey(EXAMINE_MODE_KEY,
1083 			LDrawModelViewer::EMFree, false) == LDrawModelViewer::EMLatLong;
1084 		m_modelBoundingBox = m_ldviewWindow->isBoundingBoxVisible();
1085 		m_topmost = m_ldviewWindow->isTopmost();
1086 		syncViewMode();
1087 		addTbCheckButtonInfo(m_mainButtonInfos,
1088 			ls(_UC("Wireframe")), IDC_WIREFRAME,
1089 			m_drawWireframe, TBSTYLE_CHECK | TBSTYLE_DROPDOWN);
1090 		addTbCheckButtonInfo(m_mainButtonInfos,
1091 			ls(_UC("Seams")), IDC_SEAMS, m_seams);
1092 		addTbCheckButtonInfo(m_mainButtonInfos,
1093 			ls(_UC("EdgeLines")), IDC_HIGHLIGHTS, m_edges,
1094 			TBSTYLE_CHECK | TBSTYLE_DROPDOWN);
1095 		addTbCheckButtonInfo(m_mainButtonInfos,
1096 			ls(_UC("PrimitiveSubstitution")),
1097 			IDC_PRIMITIVE_SUBSTITUTION, m_primitiveSubstitution,
1098 			TBSTYLE_CHECK | TBSTYLE_DROPDOWN);
1099 		addTbCheckButtonInfo(m_mainButtonInfos,
1100 			ls(_UC("Lighting")), IDC_LIGHTING, m_lighting,
1101 			TBSTYLE_CHECK | TBSTYLE_DROPDOWN);
1102 		addTbButtonInfo(m_mainButtonInfos,
1103 			ls(_UC("RightSideUp")), ID_VIEW_RIGHTSIDEUP);
1104 		addTbButtonInfo(m_mainButtonInfos,
1105 			ls(_UC("SelectView")), ID_VIEWANGLE,
1106 			TBSTYLE_DROPDOWN | BTNS_WHOLEDROPDOWN);
1107 		IntVector viewCommandIds;
1108 		viewCommandIds.push_back(ID_VIEW_EXAMINE);
1109 		viewCommandIds.push_back(ID_VIEW_FLYTHROUGH);
1110 		viewCommandIds.push_back(ID_VIEW_WALK);
1111 		addTbStateButtonInfo(m_mainButtonInfos,
1112 			ls(_UC("ViewMode")), viewCommandIds, m_viewMode);
1113 		addTbButtonInfo(m_mainButtonInfos,
1114 			ls(_UC("Preferences")), ID_EDIT_PREFERENCES);
1115 		addTbCheckButtonInfo(m_mainButtonInfos,
1116 			ls(_UC("ViewLatLonRot")),
1117 			ID_VIEW_EXAMINE_LAT_LONG, m_examineLatLong);
1118 		addTbCheckButtonInfo(m_mainButtonInfos,
1119 			ls(_UC("TransDefaultColor")),
1120 			IDC_TRANS_DEFAULT_COLOR, m_transDefaultColor);
1121 		addTbCheckButtonInfo(m_mainButtonInfos,
1122 			ls(_UC("RandomColors")), IDC_RANDOM_COLORS,
1123 			m_randomColors);
1124 		addTbCheckButtonInfo(m_mainButtonInfos,
1125 			ls(_UC("ShowAxes")), IDC_SHOW_AXES, m_showAxes);
1126 		addTbCheckButtonInfo(m_mainButtonInfos,
1127 			ls(_UC("PartBoundingBoxesOnly")),
1128 			IDC_PART_BOUNDING_BOXES, m_partBBoxes);
1129 		addTbCheckButtonInfo(m_mainButtonInfos, ls(_UC("BFC")),
1130 			IDC_BFC, m_bfc, TBSTYLE_CHECK | TBSTYLE_DROPDOWN);
1131 		addTbCheckButtonInfo(m_mainButtonInfos,
1132 			ls(_UC("ShowAllConditionals")), IDC_ALL_CONDITIONAL,
1133 			m_allConditionals);
1134 		addTbCheckButtonInfo(m_mainButtonInfos,
1135 			ls(_UC("ShowConditionalControls")),
1136 			IDC_CONDITIONAL_CONTROLS, m_conditionalControls);
1137 		addTbCheckButtonInfo(m_mainButtonInfos,
1138 			ls(_UC("WireframeCutaway")), IDC_CUTAWAY,
1139 			m_wireframeCutaway);
1140 		addTbCheckButtonInfo(m_mainButtonInfos,
1141 			ls(_UC("FlatShading")), IDC_FLAT_SHADING, m_flat);
1142 		addTbCheckButtonInfo(m_mainButtonInfos,
1143 			ls(_UC("SmoothCurves")), IDC_SMOOTH_CURVES,
1144 			m_smoothCurves);
1145 		addTbCheckButtonInfo(m_mainButtonInfos, ls(_UC("Texmaps")),
1146 			ID_PRIMITIVES_TEXMAPS, m_texmaps);
1147 		addTbCheckButtonInfo(m_mainButtonInfos,
1148 			ls(_UC("TextureStuds")),
1149 			ID_PRIMITIVES_TEXTURESTUDS, m_prefs->getTextureStuds());
1150 		addTbCheckButtonInfo(m_mainButtonInfos,
1151 			ls(_UC("LowQualityStuds")), IDC_STUD_QUALITY,
1152 			m_lowStuds);
1153 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("Export")),
1154 			ID_FILE_EXPORT);
1155 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("Print")),
1156 			ID_FILE_PRINT);
1157 		addTbButtonInfo(m_mainButtonInfos,
1158 			ls(_UC("FullScreen")), ID_VIEW_FULLSCREEN);
1159 		addTbCheckButtonInfo(m_mainButtonInfos,
1160 			ls(_UC("AlwaysOnTop")), ID_VIEW_ALWAYSONTOP,
1161 			m_topmost);
1162 		addTbButtonInfo(m_mainButtonInfos,
1163 			ls(_UC("ZoomToFit")), ID_VIEW_ZOOMTOFIT);
1164 		addTbButtonInfo(m_mainButtonInfos,
1165 			ls(_UC("FrontView")), ID_VIEW_FRONT);
1166 		addTbButtonInfo(m_mainButtonInfos,
1167 			ls(_UC("BackView")), ID_VIEW_BACK);
1168 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("LeftView")),
1169 			ID_VIEW_LEFT);
1170 		addTbButtonInfo(m_mainButtonInfos,
1171 			ls(_UC("RightView")), ID_VIEW_RIGHT);
1172 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("TopView")),
1173 			ID_VIEW_TOP);
1174 		addTbButtonInfo(m_mainButtonInfos,
1175 			ls(_UC("BottomView")), ID_VIEW_BOTTOM);
1176 		addTbButtonInfo(m_mainButtonInfos,
1177 			ls(_UC("LatLonView")), ID_VIEW_SPECIFYLATLON);
1178 		addTbButtonInfo(m_mainButtonInfos,
1179 			ls(_UC("TwoThirdsView")), ID_VIEW_ISO);
1180 		addTbButtonInfo(m_mainButtonInfos,
1181 			ls(_UC("ErrorsAndWarnings")), ID_TOOLS_ERRORS);
1182 		addTbButtonInfo(m_mainButtonInfos,
1183 			ls(_UC("PartsList")), ID_TOOLS_PARTSLIST);
1184 		addTbButtonInfo(m_mainButtonInfos,
1185 			ls(_UC("ModelTree")), ID_TOOLS_MODELTREE);
1186 		addTbCheckButtonInfo(m_mainButtonInfos,
1187 			ls(_UC("ModelBBox")), ID_TOOLS_BOUNDINGBOX,
1188 			m_modelBoundingBox);
1189 		addTbButtonInfo(m_mainButtonInfos,
1190 			ls(_UC("MPDModelSelection")), ID_TOOLS_MPD);
1191 		addTbButtonInfo(m_mainButtonInfos,
1192 			ls(_UC("POVCameraInfo")), ID_TOOLS_POV_CAMERA);
1193 		addTbButtonInfo(m_mainButtonInfos, ls(_UC("Help")),
1194 			ID_HELP_CONTENTS);
1195 	}
1196 }
1197 
doToolbarGetInfotip(TbButtonInfoVector & infos,LPNMTBGETINFOTIPUC dispInfo)1198 LRESULT ToolbarStrip::doToolbarGetInfotip(
1199 	TbButtonInfoVector &infos,
1200 	LPNMTBGETINFOTIPUC dispInfo)
1201 {
1202 	int i;
1203 	int count = (int)infos.size();
1204 
1205 	for (i = 0; i < count; i++)
1206 	{
1207 		TbButtonInfo &buttonInfo = infos[i];
1208 
1209 		if (buttonInfo.getCommandId() == dispInfo->iItem)
1210 		{
1211 			if (CUIThemes::isThemeLibLoaded())
1212 			{
1213 				//HWND hTooltip = (HWND)SendMessage(dispInfo->hdr.hwndFrom,
1214 				//	TB_GETTOOLTIPS, 0, 0);
1215 				//// Turning off theme support in the tooltip makes it
1216 				//// work properly.  With theme support on, it gets erased
1217 				//// by the OpenGL window immediately after being drawn.
1218 				//// Haven't the foggiest why this happens, but turning
1219 				//// off theme support solves the problem.  This has to
1220 				//// be done every time the tooltip is about to pop up.
1221 				//// Not sure why that is either, but it is.
1222 				//CUIThemes::setWindowTheme(hTooltip, NULL, L"");
1223 			}
1224 			if (m_ldviewWindow->getLoading())
1225 			{
1226 				// Don't allow tooltips to pop up while loading; they
1227 				// prevent the loading from continuing until they go
1228 				// away.
1229 				dispInfo->pszText = NULL;
1230 			}
1231 			else
1232 			{
1233 				ucstrncpy(dispInfo->pszText, buttonInfo.getTooltipText(),
1234 					dispInfo->cchTextMax);
1235 				dispInfo->pszText[dispInfo->cchTextMax - 1] = 0;
1236 			}
1237 			break;
1238 		}
1239 	}
1240 	return 0;
1241 }
1242 
doMainTbGetButtonInfo(NMTOOLBARUC * notification)1243 LRESULT ToolbarStrip::doMainTbGetButtonInfo(NMTOOLBARUC *notification)
1244 {
1245 	int index = notification->iItem;
1246 	int skipCount = 0;
1247 
1248 	for (int i = 0; i <= index && i + skipCount < (int)m_mainButtonInfos.size();
1249 		i++)
1250 	{
1251 		if (m_mainButtonInfos[i].getStyle() == TBSTYLE_SEP)
1252 		{
1253 			skipCount++;
1254 		}
1255 	}
1256 	if (index + skipCount < (int)m_mainButtonInfos.size())
1257 	{
1258 		TbButtonInfo &buttonInfo = m_mainButtonInfos[index + skipCount];
1259 
1260 		ucstrncpy(notification->pszText, buttonInfo.getTooltipText(),
1261 			notification->cchText);
1262 		notification->pszText[notification->cchText - 1] = 0;
1263 		notification->cchText = (int)ucstrlen(notification->pszText);
1264 		fillTbButton(notification->tbButton, buttonInfo);
1265 		SetWindowLongPtr(hWindow, DWLP_MSGRESULT, TRUE);
1266 		return TRUE;
1267 	}
1268 	SetWindowLongPtr(hWindow, DWLP_MSGRESULT, FALSE);
1269 	return FALSE;
1270 }
1271 
doMainToolbarReset(void)1272 LRESULT ToolbarStrip::doMainToolbarReset(void)
1273 {
1274 	for (int i = 0; true; i++)
1275 	{
1276 		if (SendMessage(m_hToolbar, TB_DELETEBUTTON, 0, 0))
1277 		{
1278 			char key[128];
1279 
1280 			sprintf(key, "%s%02d", MAIN_TOOLBAR_IDS_KEY, i);
1281 			TCUserDefaults::removeValue(key, false);
1282 		}
1283 		else
1284 		{
1285 			break;
1286 		}
1287 
1288 	}
1289 	fillMainToolbar();
1290 	initLayout();
1291 	return 0;
1292 }
1293 
doMainToolbarChange(void)1294 LRESULT ToolbarStrip::doMainToolbarChange(void)
1295 {
1296 	LongVector mainButtonIDs;
1297 
1298 	for (int i = 0; true; i++)
1299 	{
1300 		TBBUTTON button;
1301 
1302 		if (SendMessage(m_hToolbar, TB_GETBUTTON, i, (LPARAM)&button))
1303 		{
1304 			mainButtonIDs.push_back(button.idCommand);
1305 		}
1306 		else
1307 		{
1308 			break;
1309 		}
1310 	}
1311 	TCUserDefaults::setLongVectorForKey(mainButtonIDs, MAIN_TOOLBAR_IDS_KEY,
1312 		false);
1313 	sizeToolbar(m_hToolbar, (int)mainButtonIDs.size());
1314 	initLayout();
1315 	return 0;	// ignored
1316 }
1317 
doMainToolbarNotify(int controlId,LPNMHDR notification)1318 LRESULT ToolbarStrip::doMainToolbarNotify(int controlId, LPNMHDR notification)
1319 {
1320 	//debugPrintf("LDViewWindow::doMainToolbarNotify: 0x%04X, %s\n", controlId,
1321 	//	notificationName(notification->code).c_str());
1322 	switch (notification->code)
1323 	{
1324 	case TBN_GETINFOTIPUC:
1325 		return doToolbarGetInfotip(m_mainButtonInfos,
1326 			(LPNMTBGETINFOTIPUC)notification);
1327 	case TBN_DROPDOWN:
1328 		if (notification->idFrom == ID_TOOLBAR ||
1329 			notification->idFrom == IDC_TOOLBAR)
1330 		{
1331 			doDropDown((LPNMTOOLBAR)notification);
1332 		}
1333 		break;
1334 	case TBN_QUERYDELETE:
1335 	case TBN_QUERYINSERT:
1336 		SetWindowLongPtr(hWindow, DWLP_MSGRESULT, TRUE);
1337 		return TRUE;
1338 	case TBN_GETBUTTONINFOUC:
1339 		return doMainTbGetButtonInfo((NMTOOLBARUC *)notification);
1340 	case TBN_TOOLBARCHANGE:
1341 		return doMainToolbarChange();
1342 	case TBN_RESET:
1343 		return doMainToolbarReset();
1344 	default:
1345 		return CUIWindow::doNotify(controlId, notification);
1346 	}
1347 	return 0;
1348 }
1349 
doStepToolbarNotify(int controlId,LPNMHDR notification)1350 LRESULT ToolbarStrip::doStepToolbarNotify(int controlId, LPNMHDR notification)
1351 {
1352 	//debugPrintf("LDViewWindow::doStepToolbarNotify: 0x%04X, %s\n", controlId,
1353 	//	notificationName(notification->code).c_str());
1354 	switch (notification->code)
1355 	{
1356 	case TBN_GETINFOTIPUC:
1357 		return doToolbarGetInfotip(m_stepButtonInfos,
1358 			(LPNMTBGETINFOTIPUC)notification);
1359 	default:
1360 		return CUIWindow::doNotify(controlId, notification);
1361 	}
1362 	return 0;
1363 }
1364 
doNotify(int controlId,LPNMHDR notification)1365 LRESULT ToolbarStrip::doNotify(int controlId, LPNMHDR notification)
1366 {
1367 	if (notification->hwndFrom == m_hToolbar)
1368 	{
1369 		return doMainToolbarNotify(controlId, notification);
1370 	}
1371 	else if (notification->hwndFrom == m_hStepToolbar)
1372 	{
1373 		return doStepToolbarNotify(controlId, notification);
1374 	}
1375 	else
1376 	{
1377 		return CUIDialog::doNotify(controlId, notification);
1378 	}
1379 }
1380 
enableMainToolbarButton(UINT buttonId,bool enable)1381 void ToolbarStrip::enableMainToolbarButton(UINT buttonId, bool enable)
1382 {
1383 	enableToolbarButton(m_hToolbar, buttonId, enable);
1384 }
1385 
updateContextMenu(void)1386 void ToolbarStrip::updateContextMenu(void)
1387 {
1388 	setMenuCheck(m_hContextMenu, ID_TBCONTEXT_MAIN, m_showMain);
1389 	setMenuCheck(m_hContextMenu, ID_TBCONTEXT_STEPS, m_showSteps);
1390 }
1391 
updateWireframeMenu(void)1392 void ToolbarStrip::updateWireframeMenu(void)
1393 {
1394 	setMenuCheck(m_hWireframeMenu, ID_WIREFRAME_FOG,
1395 		m_prefs->getUseWireframeFog());
1396 	setMenuCheck(m_hWireframeMenu, ID_WIREFRAME_REMOVEHIDDENLINES,
1397 		m_prefs->getRemoveHiddenLines());
1398 	setMenuItemsEnabled(m_hWireframeMenu, m_drawWireframe);
1399 }
1400 
updateEdgesMenu(void)1401 void ToolbarStrip::updateEdgesMenu(void)
1402 {
1403 	setMenuCheck(m_hEdgesMenu, ID_EDGES_SHOWEDGESONLY,
1404 		m_prefs->getEdgesOnly());
1405 	setMenuCheck(m_hEdgesMenu, ID_EDGES_CONDITIONALLINES,
1406 		m_prefs->getDrawConditionalHighlights());
1407 	setMenuCheck(m_hEdgesMenu, ID_EDGES_HIGHQUALITY,
1408 		m_prefs->getUsePolygonOffset());
1409 	setMenuCheck(m_hEdgesMenu, ID_EDGES_ALWAYSBLACK,
1410 		m_prefs->getBlackHighlights());
1411 	setMenuItemsEnabled(m_hEdgesMenu, m_edges);
1412 }
1413 
updatePrimitivesMenu(void)1414 void ToolbarStrip::updatePrimitivesMenu(void)
1415 {
1416 	setMenuCheck(m_hPrimitivesMenu, ID_PRIMITIVES_TEXTURESTUDS,
1417 		m_prefs->getTextureStuds());
1418 	setMenuCheck(m_hPrimitivesMenu, ID_PRIMITIVES_TEXMAPS,
1419 		m_texmaps);
1420 	setMenuItemsEnabled(m_hPrimitivesMenu, m_primitiveSubstitution);
1421 }
1422 
updateLightingMenu(void)1423 void ToolbarStrip::updateLightingMenu(void)
1424 {
1425 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_HIGHQUALITY,
1426 		m_prefs->getQualityLighting());
1427 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_SUBDUED,
1428 		m_prefs->getSubduedLighting());
1429 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_SPECULARHIGHLIGHT,
1430 		m_prefs->getUsesSpecular());
1431 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_ALTERNATESETUP,
1432 		m_prefs->getOneLight());
1433 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_DRAWDATS,
1434 		m_prefs->getDrawLightDats());
1435 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_OPTIONALMAIN,
1436 		m_prefs->getOptionalStandardLight());
1437 	setMenuItemsEnabled(m_hLightingMenu, m_lighting);
1438 	if (!m_prefs->getDrawLightDats())
1439 	{
1440 		setMenuEnabled(m_hLightingMenu, ID_LIGHTING_OPTIONALMAIN, false,
1441 			FALSE);
1442 		setMenuCheck(m_hLightingMenu, ID_LIGHTING_OPTIONALMAIN, false);
1443 	}
1444 }
1445 
updateBFCMenu(void)1446 void ToolbarStrip::updateBFCMenu(void)
1447 {
1448 	setMenuCheck(m_hBFCMenu, ID_BFC_REDBACKFACES,
1449 		m_prefs->getRedBackFaces());
1450 	setMenuCheck(m_hBFCMenu, ID_BFC_GREENFRONTFACES,
1451 		m_prefs->getGreenFrontFaces());
1452 	setMenuCheck(m_hBFCMenu, ID_BFC_BLUENEUTRALFACES,
1453 		m_prefs->getBlueNeutralFaces());
1454 	setMenuItemsEnabled(m_hBFCMenu, m_bfc);
1455 }
1456 
doDropDown(LPNMTOOLBAR toolbarNot)1457 void ToolbarStrip::doDropDown(LPNMTOOLBAR toolbarNot)
1458 {
1459 	RECT rect;
1460 	TPMPARAMS tpm;
1461 	HMENU hMenu = NULL;
1462 
1463     SendMessage(toolbarNot->hdr.hwndFrom, TB_GETRECT, (WPARAM)toolbarNot->iItem,
1464 		(LPARAM)&rect);
1465 	MapWindowPoints(toolbarNot->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&rect, 2);
1466 	tpm.cbSize = sizeof(TPMPARAMS);
1467 	tpm.rcExclude.top    = rect.top;
1468 	tpm.rcExclude.left   = rect.left;
1469 	tpm.rcExclude.bottom = rect.bottom;
1470 	tpm.rcExclude.right  = rect.right;
1471 	switch (toolbarNot->iItem)
1472 	{
1473 	case IDC_WIREFRAME:
1474 		hMenu = m_hWireframeMenu;
1475 		break;
1476 	case IDC_HIGHLIGHTS:
1477 		hMenu = m_hEdgesMenu;
1478 		break;
1479 	case IDC_PRIMITIVE_SUBSTITUTION:
1480 		hMenu = m_hPrimitivesMenu;
1481 		break;
1482 	case IDC_LIGHTING:
1483 		hMenu = m_hLightingMenu;
1484 		break;
1485 	case IDC_BFC:
1486 		hMenu = m_hBFCMenu;
1487 		break;
1488 	case ID_VIEWANGLE:
1489 		hMenu = m_ldviewWindow->getViewAngleMenu();
1490 		break;
1491 	}
1492 	if (hMenu)
1493 	{
1494 		BOOL fade;
1495 
1496 		// Note: selection fade causes a display glitch.  This is an obscenely
1497 		// ugly hack to get rid of that, but it does work.  The problem still
1498 		// exists when the menu item is selected from the main menu, though.
1499 		// Did I mention yet today that Microsoft sucks?
1500 		SystemParametersInfo(SPI_GETSELECTIONFADE, 0, &fade, 0);
1501 		if (fade)
1502 		{
1503 			// We better pray it doesn't crash between here and where we put
1504 			// things back below.
1505 			SystemParametersInfo(SPI_SETSELECTIONFADE, FALSE, NULL, 0);
1506 		}
1507 		TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
1508 			rect.left, rect.bottom, hWindow, &tpm);
1509 		if (fade)
1510 		{
1511 			SystemParametersInfo(SPI_SETSELECTIONFADE, 0, &fade, 0);
1512 		}
1513 	}
1514 }
1515 
forceRedraw(void)1516 void ToolbarStrip::forceRedraw(void)
1517 {
1518 	ModelWindow *modelWindow = m_ldviewWindow->getModelWindow();
1519 
1520 	if (modelWindow)
1521 	{
1522 		modelWindow->forceRedraw();
1523 	}
1524 }
1525 
doWireframe(void)1526 void ToolbarStrip::doWireframe(void)
1527 {
1528 	if (doCheck(m_drawWireframe, IDC_WIREFRAME))
1529 	{
1530 		m_prefs->setDrawWireframe(m_drawWireframe);
1531 		forceRedraw();
1532 	}
1533 }
1534 
doSeams(void)1535 void ToolbarStrip::doSeams(void)
1536 {
1537 	if (doCheck(m_seams, IDC_SEAMS))
1538 	{
1539 		m_prefs->setUseSeams(m_seams);
1540 		forceRedraw();
1541 	}
1542 }
1543 
doEdges(void)1544 void ToolbarStrip::doEdges(void)
1545 {
1546 	if (doCheck(m_edges, IDC_HIGHLIGHTS))
1547 	{
1548 		m_prefs->setShowsHighlightLines(m_edges);
1549 		forceRedraw();
1550 	}
1551 }
1552 
doPrimitiveSubstitution(void)1553 void ToolbarStrip::doPrimitiveSubstitution(void)
1554 {
1555 	if (doCheck(m_primitiveSubstitution, IDC_PRIMITIVE_SUBSTITUTION))
1556 	{
1557 		m_prefs->setAllowPrimitiveSubstitution(m_primitiveSubstitution);
1558 		forceRedraw();
1559 	}
1560 }
1561 
doLighting(void)1562 void ToolbarStrip::doLighting(void)
1563 {
1564 	if (doCheck(m_lighting, IDC_LIGHTING))
1565 	{
1566 		m_prefs->setUseLighting(m_lighting);
1567 		forceRedraw();
1568 	}
1569 }
1570 
doFog(void)1571 void ToolbarStrip::doFog(void)
1572 {
1573 	m_prefs->setUseWireframeFog(!m_prefs->getUseWireframeFog());
1574 	setMenuCheck(m_hWireframeMenu, ID_WIREFRAME_FOG,
1575 		m_prefs->getUseWireframeFog());
1576 }
1577 
doRemoveHiddenLines(void)1578 void ToolbarStrip::doRemoveHiddenLines(void)
1579 {
1580 	m_prefs->setRemoveHiddenLines(!m_prefs->getRemoveHiddenLines());
1581 	setMenuCheck(m_hWireframeMenu, ID_WIREFRAME_REMOVEHIDDENLINES,
1582 		m_prefs->getRemoveHiddenLines());
1583 }
1584 
doShowEdgesOnly(void)1585 void ToolbarStrip::doShowEdgesOnly(void)
1586 {
1587 	m_prefs->setEdgesOnly(!m_prefs->getEdgesOnly());
1588 	setMenuCheck(m_hEdgesMenu, ID_EDGES_SHOWEDGESONLY,
1589 		m_prefs->getEdgesOnly());
1590 }
1591 
doConditionalLines(void)1592 void ToolbarStrip::doConditionalLines(void)
1593 {
1594 	m_prefs->setDrawConditionalHighlights(!m_prefs->getDrawConditionalHighlights());
1595 	setMenuCheck(m_hEdgesMenu, ID_EDGES_CONDITIONALLINES,
1596 		m_prefs->getDrawConditionalHighlights());
1597 }
1598 
doHighQualityEdges(void)1599 void ToolbarStrip::doHighQualityEdges(void)
1600 {
1601 	m_prefs->setUsePolygonOffset(!m_prefs->getUsePolygonOffset());
1602 	setMenuCheck(m_hEdgesMenu, ID_EDGES_HIGHQUALITY,
1603 		m_prefs->getUsePolygonOffset());
1604 }
1605 
doAlwaysBlack(void)1606 void ToolbarStrip::doAlwaysBlack(void)
1607 {
1608 	m_prefs->setBlackHighlights(!m_prefs->getBlackHighlights());
1609 	setMenuCheck(m_hEdgesMenu, ID_EDGES_ALWAYSBLACK,
1610 		m_prefs->getBlackHighlights());
1611 }
1612 
doTexmaps(void)1613 void ToolbarStrip::doTexmaps(void)
1614 {
1615 	m_texmaps = !m_texmaps;
1616 	m_prefs->setTexmaps(m_texmaps);
1617 	setMenuCheck(m_hPrimitivesMenu, ID_PRIMITIVES_TEXMAPS, m_texmaps);
1618 	forceRedraw();
1619 	checksReflect();
1620 }
1621 
doTextureStuds(void)1622 void ToolbarStrip::doTextureStuds(void)
1623 {
1624 	m_prefs->setTextureStuds(!m_prefs->getTextureStuds());
1625 	setMenuCheck(m_hPrimitivesMenu, ID_PRIMITIVES_TEXTURESTUDS,
1626 		m_prefs->getTextureStuds());
1627 	forceRedraw();
1628 	checksReflect();
1629 }
1630 
doQualityLighting(void)1631 void ToolbarStrip::doQualityLighting(void)
1632 {
1633 	m_prefs->setQualityLighting(!m_prefs->getQualityLighting());
1634 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_HIGHQUALITY,
1635 		m_prefs->getQualityLighting());
1636 }
1637 
doSubduedLighting(void)1638 void ToolbarStrip::doSubduedLighting(void)
1639 {
1640 	m_prefs->setSubduedLighting(!m_prefs->getSubduedLighting());
1641 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_SUBDUED,
1642 		m_prefs->getSubduedLighting());
1643 }
1644 
doSpecularHighlight(void)1645 void ToolbarStrip::doSpecularHighlight(void)
1646 {
1647 	m_prefs->setUsesSpecular(!m_prefs->getUsesSpecular());
1648 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_SPECULARHIGHLIGHT,
1649 		m_prefs->getUsesSpecular());
1650 }
1651 
doAlternateLighting(void)1652 void ToolbarStrip::doAlternateLighting(void)
1653 {
1654 	m_prefs->setOneLight(!m_prefs->getOneLight());
1655 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_ALTERNATESETUP,
1656 		m_prefs->getOneLight());
1657 }
1658 
doDrawLightDats(void)1659 void ToolbarStrip::doDrawLightDats(void)
1660 {
1661 	m_prefs->setDrawLightDats(!m_prefs->getDrawLightDats());
1662 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_DRAWDATS,
1663 		m_prefs->getDrawLightDats());
1664 }
1665 
doOptionalStandardLight(void)1666 void ToolbarStrip::doOptionalStandardLight(void)
1667 {
1668 	m_prefs->setOptionalStandardLight(!m_prefs->getOptionalStandardLight());
1669 	setMenuCheck(m_hLightingMenu, ID_LIGHTING_OPTIONALMAIN,
1670 		m_prefs->getOptionalStandardLight());
1671 }
1672 
doRedBackFaces(void)1673 void ToolbarStrip::doRedBackFaces(void)
1674 {
1675 	m_prefs->setRedBackFaces(!m_prefs->getRedBackFaces());
1676 	setMenuCheck(m_hBFCMenu, ID_BFC_REDBACKFACES,
1677 		m_prefs->getRedBackFaces());
1678 }
1679 
doGreenFrontFaces(void)1680 void ToolbarStrip::doGreenFrontFaces(void)
1681 {
1682 	m_prefs->setGreenFrontFaces(!m_prefs->getGreenFrontFaces());
1683 	setMenuCheck(m_hBFCMenu, ID_BFC_GREENFRONTFACES,
1684 		m_prefs->getGreenFrontFaces());
1685 }
1686 
doBlueNeutralFaces(void)1687 void ToolbarStrip::doBlueNeutralFaces(void)
1688 {
1689 	m_prefs->setBlueNeutralFaces(!m_prefs->getBlueNeutralFaces());
1690 	setMenuCheck(m_hBFCMenu, ID_BFC_BLUENEUTRALFACES,
1691 		m_prefs->getBlueNeutralFaces());
1692 }
1693 
doCustomizeMainToolbar(void)1694 void ToolbarStrip::doCustomizeMainToolbar(void)
1695 {
1696 	SendMessage(m_hToolbar, TB_CUSTOMIZE, 0, 0);
1697 }
1698 
doMainToolbar(void)1699 void ToolbarStrip::doMainToolbar(void)
1700 {
1701 	m_showMain = !m_showMain;
1702 	TCUserDefaults::setBoolForKey(m_showMain, SHOW_MAIN_TOOLBAR_KEY, false);
1703 	initLayout();
1704 }
1705 
doViewMode(void)1706 void ToolbarStrip::doViewMode(void)
1707 {
1708 	int commandId = ID_VIEW_EXAMINE;
1709 
1710 	if (m_viewMode == LDInputHandler::VMExamine)
1711 	{
1712 		commandId = ID_VIEW_FLYTHROUGH;
1713 	}
1714 	else if (m_viewMode == LDInputHandler::VMFlyThrough)
1715 	{
1716 		commandId = ID_VIEW_WALK;
1717 	}
1718 	SendMessage(m_ldviewWindow->getHWindow(), WM_COMMAND,
1719 		MAKEWPARAM(commandId, BN_CLICKED), (LPARAM)m_hToolbar);
1720 }
1721 
doStepsToolbar(void)1722 void ToolbarStrip::doStepsToolbar(void)
1723 {
1724 	m_showSteps = !m_showSteps;
1725 	TCUserDefaults::setBoolForKey(m_showSteps, SHOW_STEPS_TOOLBAR_KEY, false);
1726 	initLayout();
1727 }
1728 
doBfc(void)1729 void ToolbarStrip::doBfc(void)
1730 {
1731 	if (doCheck(m_bfc, IDC_BFC))
1732 	{
1733 		m_prefs->setBfc(m_bfc);
1734 		forceRedraw();
1735 	}
1736 }
1737 
doShowAxes(void)1738 void ToolbarStrip::doShowAxes(void)
1739 {
1740 	if (doCheck(m_showAxes, IDC_SHOW_AXES))
1741 	{
1742 		m_prefs->setShowAxes(m_showAxes);
1743 		forceRedraw();
1744 	}
1745 }
1746 
doRandomColors(void)1747 void ToolbarStrip::doRandomColors(void)
1748 {
1749 	if (doCheck(m_randomColors, IDC_RANDOM_COLORS))
1750 	{
1751 		m_prefs->setRandomColors(m_randomColors);
1752 		forceRedraw();
1753 	}
1754 }
1755 
doAllConditionals(void)1756 void ToolbarStrip::doAllConditionals(void)
1757 {
1758 	if (doCheck(m_allConditionals, IDC_ALL_CONDITIONAL))
1759 	{
1760 		m_prefs->setShowAllConditionalLines(m_allConditionals);
1761 		forceRedraw();
1762 	}
1763 }
1764 
doConditionalControls(void)1765 void ToolbarStrip::doConditionalControls(void)
1766 {
1767 	if (doCheck(m_conditionalControls, IDC_CONDITIONAL_CONTROLS))
1768 	{
1769 		m_prefs->setShowConditionalControlPoints(m_conditionalControls);
1770 		forceRedraw();
1771 	}
1772 }
1773 
doFlatShading(void)1774 void ToolbarStrip::doFlatShading(void)
1775 {
1776 	if (doCheck(m_flat, IDC_FLAT_SHADING))
1777 	{
1778 		m_prefs->setUsesFlatShading(m_flat);
1779 		if (m_flat && m_smoothCurves)
1780 		{
1781 			m_prefs->setPerformSmoothing(false);
1782 			checksReflect();
1783 		}
1784 		forceRedraw();
1785 	}
1786 }
1787 
doCutaway(void)1788 void ToolbarStrip::doCutaway(void)
1789 {
1790 	if (doCheck(m_wireframeCutaway, IDC_CUTAWAY))
1791 	{
1792 		m_prefs->setCutawayMode(m_wireframeCutaway ? LDVCutawayWireframe :
1793 			LDVCutawayNormal);
1794 		forceRedraw();
1795 	}
1796 }
1797 
doStudQuality(void)1798 void ToolbarStrip::doStudQuality(void)
1799 {
1800 	if (doCheck(m_lowStuds, IDC_STUD_QUALITY))
1801 	{
1802 		m_prefs->setQualityStuds(!m_lowStuds);
1803 		forceRedraw();
1804 	}
1805 }
1806 
doPartBoundingBoxes(void)1807 void ToolbarStrip::doPartBoundingBoxes(void)
1808 {
1809 	if (doCheck(m_partBBoxes, IDC_PART_BOUNDING_BOXES))
1810 	{
1811 		m_prefs->setBoundingBoxesOnly(m_partBBoxes);
1812 		forceRedraw();
1813 	}
1814 }
1815 
doSmoothCurves(void)1816 void ToolbarStrip::doSmoothCurves(void)
1817 {
1818 	if (doCheck(m_smoothCurves, IDC_SMOOTH_CURVES))
1819 	{
1820 		m_prefs->setPerformSmoothing(m_smoothCurves);
1821 		if (m_flat && m_smoothCurves)
1822 		{
1823 			m_prefs->setUseFlatShading(false);
1824 			checksReflect();
1825 		}
1826 		forceRedraw();
1827 	}
1828 }
1829 
doTransDefaultColor(void)1830 void ToolbarStrip::doTransDefaultColor(void)
1831 {
1832 	if (doCheck(m_transDefaultColor, IDC_TRANS_DEFAULT_COLOR))
1833 	{
1834 		m_prefs->setTransDefaultColor(m_transDefaultColor);
1835 		forceRedraw();
1836 	}
1837 }
1838 
doCheck(bool & value,LPARAM commandId)1839 bool ToolbarStrip::doCheck(bool &value, LPARAM commandId)
1840 {
1841 	BYTE state = (BYTE)SendMessage(m_hToolbar, TB_GETSTATE, commandId, 0);
1842 	bool newValue = false;
1843 
1844 	if (state & TBSTATE_CHECKED)
1845 	{
1846 		newValue = true;
1847 	}
1848 	if (newValue != value)
1849 	{
1850 		if (m_hDeactivatedTooltip)
1851 		{
1852 			SendMessage(m_hDeactivatedTooltip, TTM_ACTIVATE, 1, 0);
1853 		}
1854 		m_hDeactivatedTooltip = (HWND)SendMessage(m_hToolbar, TB_GETTOOLTIPS, 0,
1855 			0);
1856 		SendMessage(m_hDeactivatedTooltip, TTM_POP, 0, 0);
1857 		SendMessage(m_hDeactivatedTooltip, TTM_ACTIVATE, 0, 0);
1858 		value = newValue;
1859 		return true;
1860 	}
1861 	else
1862 	{
1863 		return false;
1864 	}
1865 }
1866 
activateDeactivatedTooltip(void)1867 void ToolbarStrip::activateDeactivatedTooltip(void)
1868 {
1869 	if (m_hDeactivatedTooltip)
1870 	{
1871 		SendMessage(m_hDeactivatedTooltip, TTM_ACTIVATE, 1, 0);
1872 	}
1873 }
1874 
doInitMenuPopup(HMENU hPopupMenu,UINT,BOOL)1875 LRESULT ToolbarStrip::doInitMenuPopup(
1876 	HMENU hPopupMenu,
1877 	UINT /*uPos*/,
1878 	BOOL /*fSystemMenu*/)
1879 {
1880 	if (hPopupMenu == m_hContextMenu)
1881 	{
1882 		updateContextMenu();
1883 	}
1884 	else if (hPopupMenu == m_hWireframeMenu)
1885 	{
1886 		updateWireframeMenu();
1887 	}
1888 	else if (hPopupMenu == m_hEdgesMenu)
1889 	{
1890 		updateEdgesMenu();
1891 	}
1892 	else if (hPopupMenu == m_hPrimitivesMenu)
1893 	{
1894 		updatePrimitivesMenu();
1895 	}
1896 	else if (hPopupMenu == m_hLightingMenu)
1897 	{
1898 		updateLightingMenu();
1899 	}
1900 	else if (hPopupMenu == m_hBFCMenu)
1901 	{
1902 		updateBFCMenu();
1903 	}
1904 	return 1;
1905 }
1906 
checkReflect(bool & value,bool prefsValue,LPARAM commandID)1907 void ToolbarStrip::checkReflect(bool &value, bool prefsValue, LPARAM commandID)
1908 {
1909 	if (value != prefsValue)
1910 	{
1911 		BYTE state = (BYTE)SendMessage(m_hToolbar, TB_GETSTATE, commandID, 0);
1912 
1913 		value = prefsValue;
1914 		state &= ~TBSTATE_CHECKED;
1915 		if (value)
1916 		{
1917 			state |= TBSTATE_CHECKED;
1918 		}
1919 		SendMessage(m_hToolbar, TB_SETSTATE, commandID, MAKELONG(state, 0));
1920 	}
1921 }
1922 
viewModeReflect(void)1923 void ToolbarStrip::viewModeReflect(void)
1924 {
1925 	int oldViewMode = m_viewMode;
1926 	syncViewMode();
1927 	int bmpIndex = (int)SendMessage(m_hToolbar, TB_GETBITMAP, ID_VIEW_EXAMINE, 0);
1928 	TBBUTTONINFO bi;
1929 	bmpIndex += m_viewMode - oldViewMode;
1930 	memset(&bi, 0, sizeof(bi));
1931 	bi.cbSize = sizeof(bi);
1932 	bi.dwMask = TBIF_IMAGE;
1933 	bi.iImage = bmpIndex;
1934 	SendMessage(m_hToolbar, TB_SETBUTTONINFO, ID_VIEW_EXAMINE, (LPARAM)&bi);
1935 	checksReflect();
1936 }
1937 
checksReflect(void)1938 void ToolbarStrip::checksReflect(void)
1939 {
1940 	checkReflect(m_drawWireframe, m_prefs->getDrawWireframe(), IDC_WIREFRAME);
1941 	checkReflect(m_seams, m_prefs->getUseSeams() != 0, IDC_SEAMS);
1942 	checkReflect(m_edges, m_prefs->getShowsHighlightLines(), IDC_HIGHLIGHTS);
1943 	checkReflect(m_primitiveSubstitution,
1944 		m_prefs->getAllowPrimitiveSubstitution(), IDC_PRIMITIVE_SUBSTITUTION);
1945 	checkReflect(m_lighting, m_prefs->getUseLighting(), IDC_LIGHTING);
1946 	checkReflect(m_bfc, m_prefs->getBfc(), IDC_BFC);
1947 	checkReflect(m_showAxes, m_prefs->getShowAxes(), IDC_SHOW_AXES);
1948 	checkReflect(m_randomColors, m_prefs->getRandomColors(), IDC_RANDOM_COLORS);
1949 	checkReflect(m_allConditionals, m_prefs->getShowAllConditionalLines(),
1950 		IDC_ALL_CONDITIONAL);
1951 	checkReflect(m_conditionalControls,
1952 		m_prefs->getShowConditionalControlPoints(), IDC_CONDITIONAL_CONTROLS);
1953 	checkReflect(m_flat, m_prefs->getUseFlatShading(), IDC_FLAT_SHADING);
1954 	checkReflect(m_lowStuds, !m_prefs->getQualityStuds(), IDC_STUD_QUALITY);
1955 	checkReflect(m_partBBoxes, m_prefs->getBoundingBoxesOnly(),
1956 		IDC_PART_BOUNDING_BOXES);
1957 	checkReflect(m_smoothCurves, m_prefs->getPerformSmoothing(),
1958 		IDC_SMOOTH_CURVES);
1959 	checkReflect(m_transDefaultColor, m_prefs->getTransDefaultColor(),
1960 		IDC_TRANS_DEFAULT_COLOR);
1961 	checkReflect(m_modelBoundingBox, m_ldviewWindow->isBoundingBoxVisible(),
1962 		ID_TOOLS_BOUNDINGBOX);
1963 	checkReflect(m_topmost, m_ldviewWindow->isTopmost(), ID_VIEW_ALWAYSONTOP);
1964 	checkReflect(m_wireframeCutaway,
1965 		m_prefs->getCutawayMode() == LDVCutawayWireframe ||
1966 		m_prefs->getCutawayMode() == LDVCutawayStencil, IDC_CUTAWAY);
1967 	bool dummy = !m_prefs->getTextureStuds();
1968 	checkReflect(dummy, !dummy, ID_PRIMITIVES_TEXTURESTUDS);
1969 	checkReflect(m_texmaps, m_prefs->getTexmaps(), ID_PRIMITIVES_TEXMAPS);
1970 	if (m_viewMode == LDInputHandler::VMExamine)
1971 	{
1972 		checkReflect(m_examineLatLong,
1973 			TCUserDefaults::longForKey(EXAMINE_MODE_KEY,
1974 			LDrawModelViewer::EMFree, false) == LDrawModelViewer::EMLatLong,
1975 			ID_VIEW_EXAMINE_LAT_LONG);
1976 		enableMainToolbarButton(ID_VIEW_EXAMINE_LAT_LONG, true);
1977 	}
1978 	else
1979 	{
1980 		checkReflect(m_examineLatLong, false, ID_VIEW_EXAMINE_LAT_LONG);
1981 		enableMainToolbarButton(ID_VIEW_EXAMINE_LAT_LONG, false);
1982 	}
1983 }
1984 
doEnterMenuLoop(bool)1985 LRESULT ToolbarStrip::doEnterMenuLoop(bool /*isTrackPopupMenu*/)
1986 {
1987 	ModelWindow *modelWindow = m_ldviewWindow->getModelWindow();
1988 
1989 	if (m_ldviewWindow->getLoading())
1990 	{
1991 		return 0;
1992 	}
1993 	if (modelWindow)
1994 	{
1995 		LDrawModelViewer *modelViewer = modelWindow->getModelViewer();
1996 
1997 		if (modelViewer)
1998 		{
1999 			modelViewer->pause();
2000 		}
2001 	}
2002 	return 1;
2003 }
2004 
doExitMenuLoop(bool)2005 LRESULT ToolbarStrip::doExitMenuLoop(bool /*isTrackPopupMenu*/)
2006 {
2007 	ModelWindow *modelWindow = m_ldviewWindow->getModelWindow();
2008 
2009 	if (modelWindow)
2010 	{
2011 		LDrawModelViewer *modelViewer = modelWindow->getModelViewer();
2012 
2013 		if (modelViewer)
2014 		{
2015 			modelViewer->unpause();
2016 		}
2017 		modelWindow->forceRedraw();
2018 	}
2019 	return 1;
2020 }
2021 
doContextMenu(HWND hWnd,int xPos,int yPos)2022 LRESULT ToolbarStrip::doContextMenu(HWND hWnd, int xPos, int yPos)
2023 {
2024 	if (m_hContextMenu != NULL)
2025 	{
2026 		BOOL fade;
2027 
2028 		//setMenuEnabled(m_hContextMenu, ID_TBCONTEXT_CUSTOMIZE,
2029 		//	hWnd == m_hToolbar);
2030 		// Note: selection fade causes a display glitch.  This is an obscenely
2031 		// ugly hack to get rid of that, but it does work.  The problem still
2032 		// exists when the menu item is selected from the main menu, though.
2033 		// Did I mention yet today that Microsoft sucks?
2034 		SystemParametersInfo(SPI_GETSELECTIONFADE, 0, &fade, 0);
2035 		if (fade)
2036 		{
2037 			// We better pray it doesn't crash between here and where we put
2038 			// things back below.
2039 			SystemParametersInfo(SPI_SETSELECTIONFADE, FALSE, NULL, 0);
2040 		}
2041 		TrackPopupMenuEx(m_hContextMenu,
2042 			TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
2043 			xPos, yPos, hWindow, NULL);
2044 		if (fade)
2045 		{
2046 			SystemParametersInfo(SPI_SETSELECTIONFADE, 0, &fade, 0);
2047 		}
2048 		return 0;
2049 	}
2050 	return CUIDialog::doContextMenu(hWnd, xPos, yPos);
2051 }
2052