root / trunk / win / Mainfrm.cpp

Revision 723, 46.4 kB (checked in by Leo, 7 months ago)

Rewrote messaging system.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// MainFrm.cpp : implementation of the CMainFrame class
2//
3
4#include "lc_global.h"
5#include <afxrich.h>
6#include <afxpriv.h>
7#include "LeoCAD.h"
8#include "MainFrm.h"
9#include "project.h"
10#include "globals.h"
11#include "mainwnd.h"
12#include "cadview.h"
13#include "console.h"
14#include "keyboard.h"
15#include "system.h"
16#include "library.h"
17#include "Print.h"
18#include "view.h"
19
20#include "lc_application.h"
21#include "lc_camera.h"
22
23#ifdef _DEBUG
24#define new DEBUG_NEW
25#undef THIS_FILE
26static char THIS_FILE[] = __FILE__;
27#endif
28
29#define TOOLBAR_VERSION 1
30#define LC_ANIM_TIMER 100
31
32void MainFrameTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
33{
34    lcGetActiveProject()->CheckAnimation();
35}
36
37static void mainframe_console_func(LC_CONSOLE_LEVEL level, const char* text, void* user_data)
38{
39    CRichEditCtrl& ctrl = ((CRichEditView *) user_data)->GetRichEditCtrl ();
40    CHARFORMAT cf;
41
42    cf.cbSize = sizeof (cf);
43    cf.dwMask = CFM_COLOR;
44    cf.dwEffects = 0;
45
46    switch (level)
47    {
48    case LC_CONSOLE_ERROR:
49        cf.crTextColor = RGB (255, 0, 0);
50        break;
51
52    case LC_CONSOLE_WARNING:
53        cf.crTextColor = RGB (0, 0, 255);
54        break;
55
56    case LC_CONSOLE_DEBUG:
57        cf.crTextColor = RGB (0, 128, 0);
58        break;
59
60    case LC_CONSOLE_MISC:
61    default:
62        cf.crTextColor = RGB (0, 0, 0);
63        break;
64    }
65
66    ctrl.SetRedraw(FALSE);
67
68    // Go to the end of the window text.
69    int TextStart = ctrl.GetWindowTextLength();
70    ctrl.SetSel(TextStart, -1);
71
72    // Change color.
73    ctrl.SetSelectionCharFormat(cf);
74
75    // Append new text.
76    ctrl.ReplaceSel(text);
77
78    ctrl.SetRedraw(TRUE);
79    ctrl.InvalidateRect(NULL, FALSE);
80}
81
82/////////////////////////////////////////////////////////////////////////////
83// CMainFrame
84
85IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
86
87BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
88    //{{AFX_MSG_MAP(CMainFrame)
89    ON_WM_CREATE()
90    ON_WM_CLOSE()
91    ON_WM_SETFOCUS()
92    ON_WM_DRAWITEM()
93    ON_WM_MEASUREITEM()
94    ON_WM_MENUCHAR()
95    ON_WM_INITMENUPOPUP()
96    ON_COMMAND(ID_VIEW_FULLSCREEN, OnViewFullscreen)
97    ON_WM_GETMINMAXINFO()
98    ON_COMMAND(ID_FILE_PRINTPIECELIST, OnFilePrintPieceList)
99    ON_WM_ACTIVATEAPP()
100    ON_COMMAND(ID_VIEW_NEWVIEW, OnViewNewView)
101    ON_MESSAGE(WM_SETMESSAGESTRING, OnSetMessageString)
102    ON_WM_DROPFILES()
103    //}}AFX_MSG_MAP
104    ON_COMMAND_RANGE(ID_PIECEBAR_NUMBERS, ID_PIECEBAR_SUBPARTS, OnPieceBar)
105    ON_UPDATE_COMMAND_UI_RANGE(ID_PIECEBAR_NUMBERS, ID_PIECEBAR_SUBPARTS, OnUpdatePieceBar)
106    // Global help commands
107    ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder)
108    ON_COMMAND(ID_HELP, CFrameWnd::OnHelp)
109    ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp)
110    ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder)
111    // User messages
112    ON_MESSAGE(WM_LC_UPDATE_LIST, OnUpdateList)
113    ON_MESSAGE(WM_LC_POPUP_CLOSE, OnPopupClose)
114    ON_MESSAGE(WM_LC_ADD_COMBO_STRING, OnAddString)
115    ON_MESSAGE(WM_LC_UPDATE_SETTINGS, UpdateSettings)
116    // Toolbar show/hide
117    ON_COMMAND_EX(ID_VIEW_ANIMATION_BAR, OnBarCheck)
118    ON_COMMAND_EX(ID_VIEW_TOOLS_BAR, OnBarCheck)
119    ON_COMMAND_EX(ID_VIEW_PIECES_BAR, OnBarCheck)
120    ON_COMMAND_EX(ID_VIEW_MODIFY_BAR, OnBarCheck)
121    ON_UPDATE_COMMAND_UI(ID_VIEW_ANIMATION_BAR, OnUpdateControlBarMenu)
122    ON_UPDATE_COMMAND_UI(ID_VIEW_TOOLS_BAR, OnUpdateControlBarMenu)
123    ON_UPDATE_COMMAND_UI(ID_VIEW_PIECES_BAR, OnUpdateControlBarMenu)
124    ON_UPDATE_COMMAND_UI(ID_VIEW_MODIFY_BAR, OnUpdateControlBarMenu)
125    ON_COMMAND(ID_VIEW_SPLITVERTICALLY, OnViewSplitVertically)
126    ON_COMMAND(ID_VIEW_SPLITHORIZONTALLY, OnViewSplitHorizontally)
127    ON_COMMAND(ID_VIEW_DELETEVIEW, OnViewDeleteView)
128    ON_COMMAND(ID_VIEW_RESETVIEWS, OnViewResetViews)
129END_MESSAGE_MAP()
130
131static UINT indicators[] =
132    { ID_SEPARATOR, ID_INDICATOR_POSITION, ID_INDICATOR_SNAP, ID_INDICATOR_STEP };
133
134/////////////////////////////////////////////////////////////////////////////
135// CMainFrame construction/destruction
136
137CMainFrame::CMainFrame()
138{
139    m_pwndFullScrnBar = NULL;
140    m_bAutoMenuEnable = FALSE;
141}
142
143CMainFrame::~CMainFrame()
144{
145    for (int i = 0; i < m_SplitterList.GetSize(); i++)
146        delete m_SplitterList[i];
147}
148
149int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
150{
151    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
152        return -1;
153
154    if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
155    {
156        TRACE0("Failed to create status bar\n");
157        return -1;      // fail to create
158    }
159    m_wndStatusBar.SetPaneStyle(0, SBPS_STRETCH|SBPS_NORMAL);
160
161    if (!m_wndStandardBar.Create(this) || !m_wndStandardBar.LoadToolBar(IDR_MAINFRAME))
162    {
163        TRACE0("Failed to create toolbar\n");
164        return -1;      // fail to create
165    }
166
167    m_wndStandardBar.SetBarStyle(m_wndStandardBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
168    m_wndStandardBar.SetWindowText(_T("Standard"));
169    m_wndStandardBar.SendMessage(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS);
170    m_wndStandardBar.SetButtonStyle(m_wndStandardBar.CommandToIndex(ID_LOCK_ON), m_wndStandardBar.GetButtonStyle(m_wndStandardBar.CommandToIndex(ID_LOCK_ON)) | TBSTYLE_DROPDOWN);
171    m_wndStandardBar.SetButtonStyle(m_wndStandardBar.CommandToIndex(ID_SNAP_ON), m_wndStandardBar.GetButtonStyle(m_wndStandardBar.CommandToIndex(ID_SNAP_ON)) | TBSTYLE_DROPDOWN);
172    m_wndStandardBar.EnableDocking(CBRS_ALIGN_ANY);
173
174    if (!m_wndToolsBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP, ID_VIEW_TOOLS_BAR) ||
175        !m_wndToolsBar.LoadToolBar(IDR_TOOLSBAR))
176    {
177        TRACE0("Failed to create toolbar\n");
178        return -1;      // fail to create
179    }
180
181    m_wndToolsBar.SetBarStyle(m_wndToolsBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
182    m_wndToolsBar.SetWindowText(_T("Drawing"));
183    m_wndToolsBar.EnableDocking(CBRS_ALIGN_ANY);
184
185    if (!m_wndAnimationBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP, ID_VIEW_ANIMATION_BAR) ||
186        !m_wndAnimationBar.LoadToolBar(IDR_ANIMATORBAR))
187    {
188        TRACE0("Failed to create toolbar\n");
189        return -1;      // fail to create
190    }
191
192    m_wndAnimationBar.SetBarStyle(m_wndAnimationBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
193    m_wndAnimationBar.SetWindowText(_T("Animation"));
194    m_wndAnimationBar.EnableDocking(CBRS_ALIGN_ANY);
195
196    if (!m_wndPiecesBar.Create(_T("Pieces"), this, CSize(200, 100),
197        TRUE, ID_VIEW_PIECES_BAR))
198    {
199        TRACE0("Failed to create pieces bar\n");
200        return -1;      // fail to create
201    }
202
203    if (!m_wndModifyDlg.Create(_T("Modify"), this, ID_VIEW_MODIFY_BAR))
204    {
205        TRACE0("Failed to create modify dialog bar\n");
206        return -1;      // fail to create
207    }
208
209    EnableDocking(CBRS_ALIGN_ANY);
210    m_wndModifyDlg.SetBarStyle(m_wndModifyDlg.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
211    m_wndModifyDlg.EnableDocking(CBRS_ALIGN_ANY);
212    ShowControlBar(&m_wndModifyDlg, FALSE, FALSE);
213    FloatControlBar(&m_wndModifyDlg, CPoint(10,10));
214
215    // To change the resizable control bar sizes, just change the following
216    // members. If you need to change them later, don't forget to call
217    // RecalcLayout() or DelayRecalcLayout() after you set the size.
218    // You can use this technique to load/save the size of the control bar.
219//  m_wndPiecesBar.m_sizeVert = CSize(226, -1); // y size ignored (stretched)
220//  m_wndPiecesBar.m_sizeFloat = CSize(226, 270);
221    m_wndPiecesBar.SetBarStyle(m_wndPiecesBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
222    m_wndPiecesBar.EnableDocking(CBRS_ALIGN_ANY);
223
224    DockControlBar(&m_wndStandardBar);
225    DockControlBar(&m_wndToolsBar);
226    DockControlBar(&m_wndPiecesBar, AFX_IDW_DOCKBAR_RIGHT);
227
228    CRect rect;
229    RecalcLayout(TRUE);
230    m_wndToolsBar.GetWindowRect(&rect);
231    rect.OffsetRect(1,0);
232    DockControlBar(&m_wndAnimationBar, AFX_IDW_DOCKBAR_TOP, &rect);
233
234    if (theApp.GetProfileInt(_T("Settings"), _T("ToolBarVersion"), 0) == TOOLBAR_VERSION)
235    {
236        CSizingControlBar::GlobalLoadState(this, "SizingBars");
237        LoadBarState("Toolbars");
238    }
239
240    // Bitmap menus are cool !
241    CMenu* pMenu = GetMenu();
242    if (pMenu)
243        pMenu->DestroyMenu();
244    HMENU hMenu = NewMenu();
245    pMenu = CMenu::FromHandle(hMenu);
246    SetMenu(pMenu);
247    m_hMenuDefault = hMenu;
248
249    UpdateMenuAccelerators();
250
251    main_window->SetXID(this);
252
253    console.SetWindowCallback(&mainframe_console_func, m_wndSplitter.GetPane(1, 0));
254
255    // Load default view layout.
256    const char* Layout = main_window->GetViewLayout(false);
257    SetViewLayout(NULL, Layout);
258
259    SetTimer(LC_ANIM_TIMER, 1000/60, (TIMERPROC)&MainFrameTimer);
260
261    return 0;
262}
263
264BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
265{
266    int status = theApp.GetProfileInt("Settings", "Window Status", -1);
267    cs.style &= ~WS_VISIBLE;
268
269    if (status != -1)
270    {
271        int r,l,b,t;
272        char szBuf[60];
273        strcpy(szBuf, theApp.GetProfileString("Settings","Window Position"));
274        sscanf(szBuf,"%d, %d, %d, %d", &t, &r, &b, &l);
275
276        cs.cx = r - l;
277        cs.cy = b - t;
278       
279        RECT workArea;
280        SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
281        l += workArea.left;
282        t += workArea.top;
283
284        cs.x = min(l, GetSystemMetrics(SM_CXSCREEN) - GetSystemMetrics(SM_CXICON));
285        cs.y = min(t, GetSystemMetrics(SM_CYSCREEN) - GetSystemMetrics(SM_CYICON));
286    }
287
288    return CFrameWnd::PreCreateWindow(cs);
289}
290
291/////////////////////////////////////////////////////////////////////////////
292// CMainFrame diagnostics
293
294#ifdef _DEBUG
295void CMainFrame::AssertValid() const
296{
297    CFrameWnd::AssertValid();
298}
299
300void CMainFrame::Dump(CDumpContext& dc) const
301{
302    CFrameWnd::Dump(dc);
303}
304
305#endif //_DEBUG
306
307/////////////////////////////////////////////////////////////////////////////
308// CMainFrame message handlers
309
310// lParam = update pieces, wParam = update colors
311LONG CMainFrame::OnUpdateList(UINT lParam, LONG wParam)
312{
313    // TODO: find out if this function is really needed
314    if (wParam != 0)
315    {
316        int x = wParam-1;
317        if (x < 14)
318            x *= 2;
319        else
320            x = ((x-14)*2)+1;
321
322        m_wndPiecesBar.m_wndColorsList.SetCurColor(x);
323    }
324
325    return TRUE;
326}
327
328// Add a string to the pieces combo
329LONG CMainFrame::OnAddString(UINT lParam, LONG /*wParam*/)
330{
331    if (lParam == NULL)
332    {
333        // Clear list
334        m_wndPiecesBar.m_wndPiecesCombo.ResetContent();
335        return TRUE;
336    }
337
338    // Search if the string is already there
339    for (int i = 0; i < m_wndPiecesBar.m_wndPiecesCombo.GetCount();i++)
340    {
341        char tmp[100];
342        m_wndPiecesBar.m_wndPiecesCombo.GetLBText(i, tmp);
343        if (strcmp((char*)lParam, tmp) == 0)
344            return TRUE;
345    }
346    m_wndPiecesBar.m_wndPiecesCombo.AddString((char*)lParam);
347
348    return TRUE;
349}
350
351HMENU CMainFrame::NewMenu()
352{
353    m_bmpMenu.LoadMenu(IDR_MAINFRAME);
354    m_bmpMenu.AddFromToolBar(&m_wndStandardBar, IDR_MAINFRAME);
355
356    // The first parameter is the menu option text. If it's NULL, keep the current text
357    // The second option is the ID of the menu option, or the menu
358    // option text (use this for adding bitmaps to popup options) to change.
359    // The third option is the resource ID of the bitmap.This can also be a
360    // toolbar ID in which case the class searches the toolbar for the
361    // appropriate bitmap. Only Bitmap and Toolbar resources are supported.
362    m_bmpMenu.ModifyODMenu(NULL, ID_FILE_SAVEPICTURE, IDB_PHOTO);
363    m_bmpMenu.ModifyODMenu(NULL, ID_VIEW_PREFERENCES, IDB_PREFERENCES);
364    m_bmpMenu.ModifyODMenu(NULL, ID_VIEW_ZOOMOUT, IDB_ZOOMOUT);
365    m_bmpMenu.ModifyODMenu(NULL, ID_VIEW_ZOOMIN, IDB_ZOOMIN);
366    m_bmpMenu.ModifyODMenu(NULL, ID_VIEW_SPLITHORIZONTALLY, IDB_SPLITH);
367    m_bmpMenu.ModifyODMenu(NULL, ID_VIEW_SPLITVERTICALLY, IDB_SPLITV);
368    m_bmpMenu.ModifyODMenu(NULL, ID_VIEW_FULLSCREEN, IDB_FULLSCREEN);
369    m_bmpMenu.ModifyODMenu(NULL, ID_PIECE_DELETE, IDB_DELETE);
370    m_bmpMenu.ModifyODMenu(NULL, ID_PIECE_GROUP, IDB_GROUP);
371    m_bmpMenu.ModifyODMenu(NULL, ID_PIECE_UNGROUP, IDB_UNGROUP);
372    m_bmpMenu.ModifyODMenu(NULL, ID_MODEL_PROPERTIES, IDB_INFO);
373    m_bmpMenu.ModifyODMenu(NULL, ID_HELP_FINDER, IDB_HELP);
374    m_bmpMenu.ModifyODMenu(NULL, ID_HELP_LEOCADHOMEPAGE, IDB_HOME);
375    m_bmpMenu.ModifyODMenu(NULL, ID_HELP_SENDEMAIL, IDB_MAIL);
376
377    m_bmpMenu.ModifyODMenu(NULL, _T("Cameras"), IDB_CAMERA);
378
379/*
380    m_menubar.ModifyODMenu(NULL,"Step", IDB_STEP);
381*/
382    return m_bmpMenu.Detach();
383}
384
385void CMainFrame::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
386{
387    if(lpMeasureItemStruct->CtlType == ODT_MENU)
388    {
389        if ((lpMeasureItemStruct->itemID == ID_SNAP_XY) || (lpMeasureItemStruct->itemID == ID_SNAP_Z))
390        {
391            CTitleMenu* Menu = (CTitleMenu*)lpMeasureItemStruct->itemData;
392            Menu->MeasureItem(lpMeasureItemStruct);
393            return;
394        }
395        else if(IsMenu((HMENU)lpMeasureItemStruct->itemID))
396        {
397            CMenu* cmenu = CMenu::FromHandle((HMENU)lpMeasureItemStruct->itemID);
398            if(m_bmpMenu.IsMenu(cmenu))
399            {
400                m_bmpMenu.MeasureItem(lpMeasureItemStruct);
401                return;
402            }
403        }
404    }
405
406    CFrameWnd::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
407}
408
409void CMainFrame::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
410{
411    if ((lpDrawItemStruct->itemID == ID_SNAP_XY) || (lpDrawItemStruct->itemID == ID_SNAP_Z))
412    {
413        CTitleMenu* Menu = (CTitleMenu*)lpDrawItemStruct->itemData;
414        Menu->DrawItem(lpDrawItemStruct);
415    }
416    else
417    {
418        CFrameWnd::OnDrawItem(nIDCtl, lpDrawItemStruct);
419    }
420}
421
422LRESULT CMainFrame::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu)
423{
424    if (m_bmpMenu.IsMenu(pMenu))
425        return CBMPMenu::FindKeyboardShortcut(nChar, nFlags, pMenu);
426    else
427        return CFrameWnd::OnMenuChar(nChar, nFlags, pMenu);
428}
429
430void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
431{
432    CFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
433
434    if(!bSysMenu)
435    {
436        if(m_bmpMenu.IsMenu(pPopupMenu))
437            CBMPMenu::UpdateMenu(pPopupMenu);
438    }
439}
440
441void CMainFrame::ProcessMessage(lcMessageType Message, void* Data)
442{
443    if (Message == LC_MSG_FOCUS_OBJECT_CHANGED)
444    {
445        m_wndModifyDlg.m_ModifyDlg.UpdateInfo((lcObject*)Data);
446
447        char str[128];
448        Vector3 pos;
449
450        lcGetActiveProject()->GetFocusPosition(pos);
451        lcGetActiveProject()->ConvertToUserUnits(pos);
452
453        sprintf(str, "X: %.2f Y: %.2f Z: %.2f", pos[0], pos[1], pos[2]);
454        SetStatusBarPane(ID_INDICATOR_POSITION, str);
455    }
456}
457
458// Helper function change the text of a status bar pane and resize it.
459void CMainFrame::SetStatusBarPane(UINT ID, const char* Text)
460{
461    // Set the pane text.
462    int Index = m_wndStatusBar.CommandToIndex(ID);
463    m_wndStatusBar.SetPaneText(Index, Text);
464
465    // Resize the pane to fit the text.
466    UINT nID, nStyle; int cxWidth;
467    HFONT hFont = (HFONT)m_wndStatusBar.SendMessage(WM_GETFONT);
468    CClientDC dcScreen(NULL);
469    HGDIOBJ hOldFont = NULL;
470
471    if (hFont != NULL)
472        hOldFont = dcScreen.SelectObject(hFont);
473
474    m_wndStatusBar.GetPaneInfo(Index, nID, nStyle, cxWidth);
475    cxWidth = dcScreen.GetTextExtent(Text).cx;
476    m_wndStatusBar.SetPaneInfo(Index, nID, nStyle, cxWidth);
477
478    if (hOldFont != NULL)
479        dcScreen.SelectObject(hOldFont);
480}
481
482LONG CMainFrame::OnPopupClose(UINT /*lParam*/, LONG /*wParam*/)
483{
484    m_wndStatusBar.m_pPopup = NULL;
485    return TRUE;
486}
487
488LONG CMainFrame::UpdateSettings(UINT /*lParam*/, LONG /*wParam*/)
489{
490    int i = theApp.GetProfileInt("Settings", "Piecebar Options", 0);
491    m_wndPiecesBar.m_bSubParts = (i & PIECEBAR_SUBPARTS) != 0;
492    m_wndPiecesBar.m_bNumbers = (i & PIECEBAR_PARTNUMBERS) != 0;
493
494    RECT rc;
495    m_wndPiecesBar.GetClientRect(&rc);
496    m_wndPiecesBar.PostMessage(WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom));
497    PostMessage(WM_LC_UPDATE_LIST, 1, 0);
498
499    return TRUE;
500}
501
502void CMainFrame::OnClose()
503{
504    if (m_lpfnCloseProc != NULL && !(*m_lpfnCloseProc)(this))
505        return;
506
507    if (!lcGetActiveProject()->SaveModified())
508        return;
509
510    if (GetStyle() & WS_VISIBLE)
511    {
512        // save window size and position when destroyed
513        WINDOWPLACEMENT wp;
514        char szBuf[60];
515
516        if (m_pwndFullScrnBar)
517        {
518            m_pwndFullScrnBar->DestroyWindow();
519            delete m_pwndFullScrnBar;
520            m_wndStatusBar.ShowWindow(SW_SHOWNORMAL);
521            wp = m_wpPrev;
522        }
523        else
524        {
525            wp.length = sizeof(wp);
526            GetWindowPlacement(&wp);
527        }
528
529        wsprintf(szBuf,"%d, %d, %d, %d", wp.rcNormalPosition.top, wp.rcNormalPosition.right,
530            wp.rcNormalPosition.bottom, wp.rcNormalPosition.left);
531        theApp.WriteProfileString("Settings","Window Position", szBuf);
532        theApp.WriteProfileInt("Settings", "Window Status", wp.showCmd);
533
534        SaveBarState("Toolbars");
535        CSizingControlBar::GlobalSaveState(this, "SizingBars");
536        theApp.WriteProfileInt(_T("Settings"), _T("ToolBarVersion"), TOOLBAR_VERSION);
537    }
538
539    KillTimer(LC_ANIM_TIMER);
540
541    AfxGetApp()->HideApplication();
542    GetActiveDocument()->OnCloseDocument();
543    AfxPostQuitMessage(0);
544}
545
546void CMainFrame::OnSetFocus(CWnd* pOldWnd)
547{
548    CFrameWnd::OnSetFocus(pOldWnd);
549   
550    if (m_wndStatusBar.m_pPopup)
551        m_wndStatusBar.m_pPopup->DestroyWindow();
552}
553
554void CMainFrame::OnPieceBar(UINT nID)
555{
556    switch (nID)
557    {
558        case ID_PIECEBAR_NUMBERS:
559        {
560            m_wndPiecesBar.m_bNumbers = !m_wndPiecesBar.m_bNumbers;
561        } break;
562        case ID_PIECEBAR_SUBPARTS:
563        {
564            m_wndPiecesBar.m_bSubParts = !m_wndPiecesBar.m_bSubParts;
565            m_wndPiecesBar.RefreshPiecesTree();
566        } break;
567    }
568
569    if (nID != ID_PIECEBAR_SUBPARTS)
570    {
571        RECT rc;
572        m_wndPiecesBar.GetClientRect(&rc);
573        m_wndPiecesBar.PostMessage(WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right, rc.bottom));
574       
575        if (nID == ID_PIECEBAR_NUMBERS)
576            PostMessage(WM_LC_UPDATE_LIST, 1, 0);
577    }
578
579    UINT u = 0;
580    if (m_wndPiecesBar.m_bSubParts) u |= PIECEBAR_SUBPARTS;
581    if (m_wndPiecesBar.m_bNumbers) u |= PIECEBAR_PARTNUMBERS;
582    theApp.WriteProfileInt("Settings", "Piecebar Options", u);
583}
584
585void CMainFrame::OnUpdatePieceBar(CCmdUI* pCmdUI)
586{
587    switch (pCmdUI->m_nID)
588    {
589        case ID_PIECEBAR_NUMBERS:
590            pCmdUI->SetCheck(m_wndPiecesBar.m_bNumbers); break;
591        case ID_PIECEBAR_SUBPARTS:
592            pCmdUI->SetCheck(m_wndPiecesBar.m_bSubParts); break;
593    }
594}
595
596void CMainFrame::OnViewFullscreen()
597{
598    RECT rectDesktop;
599    WINDOWPLACEMENT wpNew;
600   
601    if (m_pwndFullScrnBar == NULL)
602    {
603        m_wndStatusBar.ShowWindow(SW_HIDE);
604        GetWindowPlacement(&m_wpPrev);
605        m_wpPrev.length = sizeof m_wpPrev;
606       
607        //Adjust RECT to new size of window
608        ::GetWindowRect(::GetDesktopWindow(), &rectDesktop);
609        ::AdjustWindowRectEx(&rectDesktop, GetStyle(), TRUE, GetExStyle());
610
611        // Remember this for OnGetMinMaxInfo()
612        m_FullScreenWindowRect = rectDesktop;
613       
614        wpNew = m_wpPrev;
615        wpNew.showCmd = SW_SHOWNORMAL;
616        wpNew.rcNormalPosition = rectDesktop;
617       
618        m_pwndFullScrnBar = new CToolBar;
619       
620        if(!m_pwndFullScrnBar->Create(this,CBRS_SIZE_DYNAMIC|CBRS_FLOATING)
621            || !m_pwndFullScrnBar->LoadToolBar(IDR_FULLSCREEN))
622        {
623            TRACE0("Failed to create toolbar\n");
624            return;      // fail to create
625        }
626       
627        //don't allow the toolbar to dock
628        m_pwndFullScrnBar->EnableDocking(0);
629        m_pwndFullScrnBar->SetWindowPos(0,30,30,
630            0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);
631        m_pwndFullScrnBar->SetWindowText(_T("Full Screen"));
632        m_pwndFullScrnBar->GetToolBarCtrl().CheckButton(ID_VIEW_FULLSCREEN, TRUE);
633        FloatControlBar(m_pwndFullScrnBar, CPoint(30,30));
634    }
635    else
636    {
637        m_pwndFullScrnBar->DestroyWindow();
638        delete m_pwndFullScrnBar;
639        m_pwndFullScrnBar = NULL;
640        m_wndStatusBar.ShowWindow(SW_SHOWNORMAL);
641        wpNew = m_wpPrev;
642    }
643
644    SetWindowPlacement(&wpNew);
645}
646
647void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
648{
649    if (m_pwndFullScrnBar != NULL)
650    {
651        lpMMI->ptMaxSize.y = m_FullScreenWindowRect.Height();
652        lpMMI->ptMaxTrackSize.y = lpMMI->ptMaxSize.y;
653        lpMMI->ptMaxSize.x = m_FullScreenWindowRect.Width();
654        lpMMI->ptMaxTrackSize.x = lpMMI->ptMaxSize.x;
655    }
656    else
657        CFrameWnd::OnGetMinMaxInfo(lpMMI);
658}
659
660void CMainFrame::GetMessageString(UINT nID, CString& rMessage) const
661{
662    if (nID >= ID_CAMERA_FIRST && nID <= ID_CAMERA_LAST)
663    {
664        lcCamera* pCamera = lcGetActiveProject()->GetActiveModel()->GetCamera(nID-ID_CAMERA_FIRST);
665        rMessage = "Use the camera \"";
666        rMessage += pCamera->m_Name;
667        rMessage += "\"";
668    }
669    else
670        CFrameWnd::GetMessageString(nID, rMessage);
671}
672
673void CMainFrame::OnFilePrintPieceList()
674{
675    AfxBeginThread(PrintPiecesFunction, this);
676}
677
678// Pass all commands to the project.
679BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
680{
681    Project* project = lcGetActiveProject();
682    int nID = LOWORD(wParam);
683
684    if (nID >= ID_SNAP_0 && nID <= ID_SNAP_9)
685    {
686        project->HandleCommand((LC_COMMANDS)(LC_EDIT_MOVEXY_SNAP_0 + nID - ID_SNAP_0), 0);
687        return TRUE;
688    }
689
690    if (nID >= ID_SNAP_10 && nID <= ID_SNAP_19)
691    {
692        project->HandleCommand((LC_COMMANDS)(LC_EDIT_MOVEZ_SNAP_0 + nID - ID_SNAP_10), 0);
693        return TRUE;
694    }
695
696    if (nID >= ID_CAMERA_FIRST && nID <= ID_CAMERA_LAST)
697    {
698        project->HandleCommand(LC_VIEW_CAMERA_MENU, nID - ID_CAMERA_FIRST);
699        return TRUE;
700    }
701   
702    if (nID >= ID_FILE_MRU_FILE1 && nID <= ID_FILE_MRU_FILE4)
703    {
704        project->HandleCommand(LC_FILE_RECENT, nID - ID_FILE_MRU_FILE1);
705        return TRUE;
706    }
707
708    if (nID >= ID_VIEWPORT01 && nID <= ID_VIEWPORT14)
709    {
710        project->HandleCommand(LC_VIEW_VIEWPORTS, nID - ID_VIEWPORT01);
711        return TRUE;
712    }
713
714    if (nID >= ID_ACTION_SELECT && nID <= ID_ACTION_ROLL)
715    {
716        project->SetAction(nID - ID_ACTION_SELECT);
717        return TRUE;
718    }
719
720    if (nID >= ID_MODEL_MODEL1 && nID <= ID_MODEL_MODEL16)
721    {
722        project->HandleCommand((LC_COMMANDS)(LC_MODEL_MODEL1 + nID - ID_MODEL_MODEL1), 0);
723        return TRUE;
724    }
725
726    switch (nID)
727    {
728        case ID_FILE_NEW: {
729            project->HandleCommand(LC_FILE_NEW, 0);
730        } break;
731
732        case ID_FILE_OPEN: {
733            project->HandleCommand(LC_FILE_OPEN, 0);
734        } break;
735
736        case ID_FILE_MERGE: {
737            project->HandleCommand(LC_FILE_MERGE, 0);
738        } break;
739
740        case ID_FILE_SAVE: {
741            project->HandleCommand(LC_FILE_SAVE, 0);
742        } break;
743
744        case ID_FILE_SAVE_AS: {
745            project->HandleCommand(LC_FILE_SAVEAS, 0);
746        } break;
747
748        case ID_FILE_SAVEPICTURE: {
749            project->HandleCommand(LC_FILE_PICTURE, 0);
750        } break;
751
752        case ID_FILE_EXPORT_3DSTUDIO: {
753            project->HandleCommand(LC_FILE_3DS, 0);
754        } break;
755
756        case ID_FILE_EXPORT_HTML: {
757            project->HandleCommand(LC_FILE_HTML, 0);
758        } break;
759
760        case ID_FILE_EXPORT_POVRAY: {
761            project->HandleCommand(LC_FILE_POVRAY, 0);
762        } break;
763
764        case ID_FILE_EXPORT_WAVEFRONT: {
765            project->HandleCommand(LC_FILE_WAVEFRONT, 0);
766        } break;
767
768        case ID_FILE_EXPORT_VRML: {
769            project->HandleCommand(LC_FILE_VRML, 0);
770        } break;
771
772        case ID_FILE_EXPORT_X3DV: {
773            project->HandleCommand(LC_FILE_X3DV, 0);
774        } break;
775
776        case ID_MODEL_NEW: {
777            project->HandleCommand(LC_MODEL_NEW, 0);
778        } break;
779
780        case ID_MODEL_DELETE: {
781            project->HandleCommand(LC_MODEL_DELETE, 0);
782        } break;
783
784        case ID_MODEL_PROPERTIES: {
785            project->HandleCommand(LC_MODEL_PROPERTIES, 0);
786        } break;
787
788        case ID_FILE_TERRAINEDITOR: {
789            project->HandleCommand(LC_FILE_TERRAIN, 0);
790        } break;
791
792        case ID_FILE_EDITPIECELIBRARY: {
793            project->HandleCommand(LC_FILE_LIBRARY, 0);
794        } break;
795
796        case ID_EDIT_REDO: {
797            project->HandleCommand(LC_EDIT_REDO, 0);
798        } break;
799
800        case ID_EDIT_UNDO: {
801            project->HandleCommand(LC_EDIT_UNDO, 0);
802        } break;
803
804        case ID_EDIT_CUT: {
805            project->HandleCommand(LC_EDIT_CUT, 0);
806        } break;
807       
808        case ID_EDIT_COPY: {
809            project->HandleCommand(LC_EDIT_COPY, 0);
810        } break;
811
812        case ID_EDIT_PASTE: {
813            project->HandleCommand(LC_EDIT_PASTE, 0);
814        } break;
815
816        case ID_EDIT_SELECTALL: {
817            project->HandleCommand(LC_EDIT_SELECT_ALL, 0);
818        } break;
819
820        case ID_EDIT_SELECTNONE: {
821            project->HandleCommand(LC_EDIT_SELECT_NONE, 0);
822        } break;
823       
824        case ID_EDIT_SELECTINVERT: {
825            project->HandleCommand(LC_EDIT_SELECT_INVERT, 0);
826        } break;
827       
828        case ID_EDIT_SELECTBYNAME: {
829            project->HandleCommand(LC_EDIT_SELECT_BYNAME, 0);
830        } break;
831
832        case ID_PIECE_INSERT: {
833            project->HandleCommand(LC_PIECE_INSERT, 0);
834        } break;
835
836        case ID_PIECE_DELETE: {
837            project->HandleCommand(LC_PIECE_DELETE, 0);
838        } break;
839
840        case ID_PIECE_MINIFIGWIZARD: {
841            project->HandleCommand(LC_PIECE_MINIFIG, 0);
842        } break;
843
844        case ID_PIECE_ARRAY: {
845            project->HandleCommand(LC_PIECE_ARRAY, 0);
846        } break;
847
848        case ID_PIECE_GROUP: {
849            project->HandleCommand(LC_PIECE_GROUP, 0);
850        } break;
851       
852        case ID_PIECE_UNGROUP: {
853            project->HandleCommand(LC_PIECE_UNGROUP, 0);
854        } break;
855       
856        case ID_PIECE_ATTACH: {
857            project->HandleCommand(LC_PIECE_GROUP_ADD, 0);
858        } break;
859
860        case ID_PIECE_DETACH: {
861            project->HandleCommand(LC_PIECE_GROUP_REMOVE, 0);
862        } break;
863
864        case ID_PIECE_EDITGROUPS: {
865            project->HandleCommand(LC_PIECE_GROUP_EDIT, 0);
866        } break;
867
868        case ID_PIECE_HIDESELECTED: {
869            project->HandleCommand(LC_PIECE_HIDE_SELECTED, 0);
870        } break;
871
872        case ID_PIECE_HIDEUNSELECTED: {
873            project->HandleCommand(LC_PIECE_HIDE_UNSELECTED, 0);
874        } break;
875       
876        case ID_PIECE_UNHIDEALL: {
877            project->HandleCommand(LC_PIECE_UNHIDE_ALL, 0);
878        } break;
879
880        case ID_PIECE_PREVIOUS: {
881            project->HandleCommand(LC_PIECE_PREVIOUS, 0);
882        } break;
883
884        case ID_PIECE_NEXT: {
885            project->HandleCommand(LC_PIECE_NEXT, 0);
886        } break;
887
888        case ID_VIEW_PREFERENCES: {
889            project->HandleCommand(LC_VIEW_PREFERENCES, 0);
890        } break;
891
892        case ID_VIEW_ZOOMIN: {
893            project->HandleCommand(LC_VIEW_ZOOMIN, 0);
894        } break;
895
896        case ID_VIEW_ZOOMOUT: {
897            project->HandleCommand(LC_VIEW_ZOOMOUT, 0);
898        } break;
899
900        case ID_ZOOM_EXTENTS: {
901            project->HandleCommand(LC_VIEW_ZOOMEXTENTS, 0);
902        } break;
903
904        case ID_VIEW_STEP_NEXT: {
905            project->HandleCommand(LC_VIEW_STEP_NEXT, 0);
906        } break;
907
908        case ID_VIEW_STEP_PREVIOUS: {
909            project->HandleCommand(LC_VIEW_STEP_PREVIOUS, 0);
910        } break;
911
912        case ID_VIEW_STEP_FIRST: {
913            project->HandleCommand(LC_VIEW_STEP_FIRST, 0);
914        } break;
915
916        case ID_VIEW_STEP_LAST: {
917            project->HandleCommand(LC_VIEW_STEP_LAST, 0);
918        } break;
919
920        case ID_VIEW_STEP_CHOOSE: {
921            project->HandleCommand(LC_VIEW_STEP_CHOOSE, 0);
922        } break;
923
924        case ID_VIEW_STEP_INSERT: {
925            project->HandleCommand(LC_VIEW_STEP_INSERT, 0);
926        } break;
927
928        case ID_VIEW_STEP_DELETE: {
929            project->HandleCommand(LC_VIEW_STEP_DELETE, 0);
930        } break;
931
932        case ID_ANIMATOR_STOP: {
933            project->HandleCommand(LC_VIEW_STOP, 0);
934        } break;
935
936        case ID_ANIMATOR_PLAY: {
937            project->HandleCommand(LC_VIEW_PLAY, 0);
938        } break;
939
940        case ID_VIEW_CAMERAS_RESET: {
941            project->HandleCommand(LC_VIEW_CAMERA_RESET, 0);
942        } break;
943
944        case ID_ANIMATOR_KEY: {
945            project->HandleCommand(LC_TOOLBAR_ADDKEYS, 0);
946        } break;
947
948        case ID_ANIMATOR_TOGGLE: {
949            project->HandleCommand(LC_TOOLBAR_ANIMATION, 0);
950        } break;
951
952        case ID_RENDER_BOX: {
953            project->HandleCommand(LC_TOOLBAR_FASTRENDER, 0);
954        } break;
955
956        case ID_RENDER_BACKGROUND: {
957            project->HandleCommand(LC_TOOLBAR_BACKGROUND, 0);
958        } break;
959
960        case ID_SNAP_SNAPX: {
961            project->HandleCommand(LC_TOOLBAR_SNAPMENU, 0);
962        } break;
963
964        case ID_SNAP_SNAPY: {
965            project->HandleCommand(LC_TOOLBAR_SNAPMENU, 1);
966        } break;
967
968        case ID_SNAP_SNAPZ: {
969            project->HandleCommand(LC_TOOLBAR_SNAPMENU, 2);
970        } break;
971
972        case ID_SNAP_ON:
973        case ID_SNAP_SNAPALL: {
974            project->HandleCommand(LC_TOOLBAR_SNAPMENU, 3);
975        } break;
976
977        case ID_SNAP_SNAPNONE: {
978            project->HandleCommand(LC_TOOLBAR_SNAPMENU, 4);
979        } break;
980
981        case ID_LOCK_LOCKX: {
982            project->HandleCommand(LC_TOOLBAR_LOCKMENU, 0);
983        } break;
984
985        case ID_LOCK_LOCKY: {
986            project->HandleCommand(LC_TOOLBAR_LOCKMENU, 1);
987        } break;
988
989        case ID_LOCK_LOCKZ: {
990            project->HandleCommand(LC_TOOLBAR_LOCKMENU, 2);
991        } break;
992
993        case ID_LOCK_UNLOCKALL: {
994            project->HandleCommand(LC_TOOLBAR_LOCKMENU, 3);
995        } break;
996
997        case ID_LOCK_2BUTTONS: {
998            project->HandleCommand(LC_TOOLBAR_LOCKMENU, 4);
999        } break;
1000
1001        case ID_LOCK_3DMOVEMENT: {
1002            project->HandleCommand(LC_TOOLBAR_LOCKMENU, 5);
1003        } break;
1004
1005        case ID_SNAP_ANGLE: {
1006            project->HandleCommand(LC_TOOLBAR_SNAPMENU, 5);
1007        } break;
1008
1009        case ID_APP_ABOUT: {
1010            project->HandleCommand(LC_HELP_ABOUT, 0);
1011        } break;
1012
1013        case ID_PIECEBAR_EDITCATEGORY:
1014        {
1015            HTREEITEM Item = m_wndPiecesBar.m_PiecesTree.GetSelectedItem();
1016
1017            if (Item == NULL)
1018                break;
1019
1020            PiecesLibrary* Lib = lcGetPiecesLibrary();
1021            CString CategoryName = m_wndPiecesBar.m_PiecesTree.GetItemText(Item);
1022            int Index = Lib->FindCategoryIndex((const char*)CategoryName);
1023
1024            if (Index == -1)
1025                break;
1026
1027            LC_CATEGORYDLG_OPTS Opts;
1028            Opts.Name = Lib->GetCategoryName(Index);
1029            Opts.Keywords = Lib->GetCategoryKeywords(Index);
1030
1031            if (SystemDoDialog(LC_DLG_EDITCATEGORY, &Opts))
1032            {
1033                String OldName = Lib->GetCategoryName(Index);
1034                Lib->SetCategory(Index, Opts.Name, Opts.Keywords);
1035                m_wndPiecesBar.UpdatePiecesTree(OldName, Opts.Name);
1036            }
1037
1038        } break;
1039
1040        case ID_PIECEBAR_NEWCATEGORY:
1041        {
1042            LC_CATEGORYDLG_OPTS Opts;
1043            Opts.Name = "New Category";
1044            Opts.Keywords = "";
1045
1046            if (SystemDoDialog(LC_DLG_EDITCATEGORY, &Opts))
1047            {
1048                PiecesLibrary* Lib = lcGetPiecesLibrary();
1049                Lib->AddCategory(Opts.Name, Opts.Keywords);
1050                m_wndPiecesBar.UpdatePiecesTree(NULL, Opts.Name);
1051            }
1052
1053        } break;
1054
1055        case ID_PIECEBAR_REMOVECATEGORY:
1056        {
1057            HTREEITEM Item = m_wndPiecesBar.m_PiecesTree.GetSelectedItem();
1058
1059            if (Item == NULL)
1060                break;
1061
1062            PiecesLibrary* Lib = lcGetPiece