2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
34 #include "../../sys/win32/rc/guied_resource.h"
35 #include "../../ui/DeviceContext.h"
38 #include "GEOptionsDlg.h"
41 static const int IDM_WINDOWCHILD = 1000;
42 static const int ID_GUIED_FILE_MRU1 = 10000;
44 static INT_PTR CALLBACK AboutDlg_WndProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
49 EndDialog ( hwnd, 1 );
61 mRecentFileMenu = NULL;
63 mRecentFileInsertPos = 0;
68 DestroyAcceleratorTable ( mAccelerators );
75 Initialize the gui editor application
78 bool rvGEApp::Initialize ( void )
83 com_editors = EDITOR_GUI;
85 Sys_GrabMouseCursor( false );
90 mInstance = win32.hInstance;
92 // Create the accelerators
93 mAccelerators = LoadAccelerators ( mInstance, MAKEINTRESOURCE(IDR_GUIED_ACCELERATORS) );
95 // Register the window classes for the main frame and the mdi child window
97 memset ( &wndClass, 0, sizeof(wndClass) );
98 wndClass.cbSize = sizeof(WNDCLASSEX);
99 wndClass.lpszClassName = "QUAKE4_GUIEDITOR_CLASS";
100 wndClass.lpfnWndProc = FrameWndProc;
101 wndClass.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE + 1);
102 wndClass.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
103 wndClass.lpszMenuName = MAKEINTRESOURCE(IDR_GUIED_MAIN);
104 wndClass.hInstance = mInstance;
105 RegisterClassEx ( &wndClass );
107 wndClass.lpszMenuName = NULL;
108 wndClass.lpfnWndProc = MDIChildProc;
109 wndClass.lpszClassName = "QUAKE4_GUIEDITOR_CHILD_CLASS";
110 wndClass.style = CS_OWNDC|CS_DBLCLKS|CS_BYTEALIGNWINDOW|CS_VREDRAW|CS_HREDRAW;
111 wndClass.hbrBackground = (HBRUSH)GetStockObject( LTGRAY_BRUSH );
112 RegisterClassEx ( &wndClass );
114 // Create the main window
115 mMDIFrame = CreateWindow ( "QUAKE4_GUIEDITOR_CLASS",
116 "Quake IV GUI Editor",
117 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS,
118 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
119 NULL, NULL, mInstance, (LPVOID)this );
126 SetClassLong( mMDIFrame, GCL_HICON, ( LONG )LoadIcon( win32.hInstance, MAKEINTRESOURCE( IDI_GUIED ) ) );
128 // Create the MDI window
129 CLIENTCREATESTRUCT ccs;
130 ccs.hWindowMenu = GetSubMenu ( GetMenu ( mMDIFrame ), 5 );
131 ccs.idFirstChild = IDM_WINDOWCHILD;
132 mMDIClient = CreateWindow ( "MDICLIENT", NULL,
133 WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
140 DestroyWindow ( mMDIFrame );
144 // hide the doom window by default
145 ::ShowWindow ( win32.hWnd, SW_HIDE );
148 mOptions.GetWindowPlacement ( "mdiframe", mMDIFrame );
149 ShowWindow ( mMDIFrame, SW_SHOW );
150 UpdateWindow ( mMDIFrame );
152 ShowWindow ( mMDIClient, SW_SHOW );
153 UpdateWindow ( mMDIClient );
161 rvGEApp::GetActiveWorkspace
163 Retrieves the workspace pointer for the active workspace. If there is no active
164 workspace then it will return NULL
167 rvGEWorkspace* rvGEApp::GetActiveWorkspace ( HWND* ret )
169 rvGEWorkspace* workspace;
173 active = (HWND)SendMessage ( mMDIClient, WM_MDIGETACTIVE, 0, NULL );
175 // Return the window handle if requested
186 return rvGEWorkspace::GetWorkspace ( active );
191 rvGEApp::TranslateAccelerator
193 Translate any accelerators destined for this window
196 bool rvGEApp::TranslateAccelerator ( LPMSG msg )
200 if ( msg->message == WM_SYSCHAR )
202 SetFocus ( GetMDIClient ( ) );
203 msg->hwnd = GetMDIClient ( );
211 focus = GetActiveWindow ( );
213 // Only use accelerators when on the main window or navigator window
214 if ( focus == mMDIClient || focus == mMDIFrame ||
215 focus == GetNavigator().GetWindow ( ) )
217 if ( ::TranslateAccelerator ( mMDIFrame, mAccelerators, msg ) )
223 if ( TranslateMDISysAccel ( mMDIClient, msg ) )
235 Runs the current frame which causes the active window to be redrawn
238 void rvGEApp::RunFrame ( void )
241 rvGEWorkspace* workspace = GetActiveWorkspace ( &wnd );
245 // Render the workspace using a temp DC
246 HDC hDC = GetDC ( wnd );
247 workspace->Render ( hDC );
248 ReleaseDC ( wnd, hDC );
252 mViewer->RunFrame ( );
259 rvGEApp::FrameWndProc
261 Main frame window procedure
264 LRESULT CALLBACK rvGEApp::FrameWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
266 rvGEApp* app = (rvGEApp*) GetWindowLong ( hWnd, GWL_USERDATA );
275 // Tell the status bar to resize
276 app->mStatusBar.Resize ( LOWORD(lParam), HIWORD(lParam) );
278 // Calculate the new client window rectangle (minus the status bar)
279 GetWindowRect ( app->mStatusBar.GetWindow ( ), &rStatus );
280 GetClientRect ( hWnd, &rClient );
282 if ( app->mOptions.GetStatusBarVisible ( ) )
284 rClient.bottom -= (rStatus.bottom-rStatus.top);
286 MoveWindow ( app->mMDIClient, 0, 0, rClient.right-rClient.left, rClient.bottom-rClient.top, FALSE );
295 // Synchronise all toolwindows to the same state.
296 for(i = 0; i < app->mToolWindows.Num(); i++)
298 if(app->mToolWindows[i] != hWnd)
300 EnableWindow(app->mToolWindows[i], wParam);
307 return app->ToolWindowActivate ( hWnd, uMsg, wParam, lParam );
310 common->ActivateTool( LOWORD( wParam ) != WA_INACTIVE );
313 case WM_INITMENUPOPUP:
314 app->HandleInitMenu ( wParam, lParam );
318 while ( app->mWorkspaces.Num ( ) )
320 SendMessage ( app->mWorkspaces[0]->GetWindow ( ), WM_CLOSE, 0, 0 );
325 app->mOptions.SetWindowPlacement ( "mdiframe", hWnd );
326 app->mOptions.Save ( );
334 result = app->HandleCommand ( wParam, lParam );
346 cs = (LPCREATESTRUCT) lParam;
347 app = (rvGEApp*)cs->lpCreateParams;
351 SetWindowLong ( hWnd, GWL_USERDATA, (LONG)app );
353 app->mMDIFrame = hWnd;
355 app->InitRecentFiles ( );
356 app->UpdateRecentFiles ( );
357 app->mNavigator.Create ( hWnd, gApp.mOptions.GetNavigatorVisible ( ) );
358 app->mTransformer.Create ( hWnd, gApp.mOptions.GetTransformerVisible ( ) );
359 app->mStatusBar.Create ( hWnd, 9999, gApp.mOptions.GetStatusBarVisible ( ) );
360 app->mProperties.Create ( hWnd, gApp.mOptions.GetPropertiesVisible ( ) );
362 // add all the tool windows to the tool window array
363 app->mToolWindows.Append ( app->mMDIFrame );
364 app->mToolWindows.Append ( app->mNavigator.GetWindow ( ) );
365 app->mToolWindows.Append ( app->mProperties.GetWindow ( ) );
366 app->mToolWindows.Append ( app->mTransformer.GetWindow ( ) );
368 SendMessage ( app->mNavigator.GetWindow ( ), WM_NCACTIVATE, true, (LONG)-1 );
369 SendMessage ( app->mProperties.GetWindow ( ), WM_NCACTIVATE, true, (LONG)-1 );
370 SendMessage ( app->mTransformer.GetWindow ( ), WM_NCACTIVATE, true, (LONG)-1 );
376 return DefFrameProc ( hWnd, app?app->mMDIClient:NULL, uMsg, wParam, lParam );
381 rvGEApp::MDIChildProc
383 MDI Child window procedure
386 LRESULT CALLBACK rvGEApp::MDIChildProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
388 rvGEWorkspace* workspace = (rvGEWorkspace*)GetWindowLong ( hWnd, GWL_USERDATA );
390 // Give the active workspace a chance to play with it
393 workspace->HandleMessage ( uMsg, wParam, lParam );
399 workspace->GetApplication ( )->mWorkspaces.Remove ( workspace );
404 LPMDICREATESTRUCT mdics;
407 // MDI windows have their creation params buried two levels deep, extract
408 // that param since it is the workspace pointer
409 cs = (LPCREATESTRUCT) lParam;
410 mdics = (LPMDICREATESTRUCT) cs->lpCreateParams;
412 // Attach the workspace to the window
413 workspace = (rvGEWorkspace*) mdics->lParam;
414 workspace->Attach ( hWnd );
416 workspace->GetApplication ( )->mWorkspaces.Append ( workspace );
422 assert ( workspace );
423 if ( (HWND)lParam == hWnd )
425 workspace->GetApplication ( )->GetNavigator().SetWorkspace(workspace);
426 workspace->GetApplication ( )->GetTransformer().SetWorkspace(workspace);
427 workspace->GetApplication ( )->GetProperties().SetWorkspace(workspace);
428 gApp.GetStatusBar ( ).SetSimple ( false );
430 else if ( lParam == NULL )
432 gApp.GetStatusBar ( ).SetSimple ( true );
437 assert ( workspace );
438 workspace->Detach ( );
453 dc = BeginPaint(hWnd, &ps);
457 workspace->Render ( dc );
466 return DefMDIChildProc ( hWnd, uMsg, wParam, lParam );
471 rvGEApp::HandleCommandSave
473 Handles the ID_GUIED_FILE_SAVE and ID_GUIED_FILE_SAVEAS commands
476 void rvGEApp::HandleCommandSave ( rvGEWorkspace* workspace, const char* filename )
480 // See if we need to browse for a filename
481 if ( workspace->IsNew ( ) || filename == NULL )
484 char szFile[MAX_PATH];
486 strcpy ( szFile, workspace->GetFilename ( ) );
488 // Initialize OPENFILENAME
489 ZeroMemory(&ofn, sizeof(OPENFILENAME));
490 ofn.lStructSize = sizeof(OPENFILENAME);
491 ofn.hwndOwner = mMDIFrame;
492 ofn.lpstrFile = szFile;
493 ofn.nMaxFile = sizeof(szFile);
494 ofn.lpstrFilter = "GUI Files\0*.GUI\0All Files\0*.*\0";
495 ofn.nFilterIndex = 1;
496 ofn.Flags = OFN_PATHMUSTEXIST;
498 // Display the save dialog box.
499 if ( !GetSaveFileName(&ofn) )
504 realFilename = ofn.lpstrFile;
505 realFilename.StripFileExtension ( );
506 realFilename.Append ( ".gui" );
508 // If the file already exists then warn about overwriting it
509 if ( _taccess ( realFilename, 0 ) == 0 )
511 if ( IDNO == MessageBox ( va("File '%s' already exists. Do you want to replace it?", realFilename.c_str()), MB_YESNO|MB_ICONQUESTION ) )
519 realFilename = filename;
522 // Now performe the file save
523 if ( workspace->SaveFile ( realFilename ) )
525 mOptions.AddRecentFile ( workspace->GetFilename ( ) );
526 UpdateRecentFiles ( );
530 MessageBox ( va("Could not write file '%s'", workspace->GetFilename()), MB_OK|MB_ICONERROR );
536 rvGEApp::HandleCommand
538 Handles the WM_COMMAND message
541 int rvGEApp::HandleCommand ( WPARAM wParam, LPARAM lParam )
544 rvGEWorkspace* workspace = GetActiveWorkspace ( &active );
546 // The recent file list needs to be handled specially
547 if ( LOWORD(wParam) >= ID_GUIED_FILE_MRU1 && LOWORD(wParam) < ID_GUIED_FILE_MRU1 + rvGEOptions::MAX_MRU_SIZE )
549 OpenFile ( mOptions.GetRecentFile ( mOptions.GetRecentFileCount() - (LOWORD(wParam)-ID_GUIED_FILE_MRU1) - 1 ) );
553 switch ( LOWORD ( wParam ) )
555 case ID_GUIED_SOURCECONTROL_CHECKIN:
556 assert ( workspace );
557 HandleCommandSave ( workspace, workspace->GetFilename ( ) );
558 workspace->CheckIn ( );
561 case ID_GUIED_SOURCECONTROL_CHECKOUT:
562 assert ( workspace );
563 workspace->CheckOut ( );
566 case ID_GUIED_SOURCECONTROL_UNDOCHECKOUT:
567 assert ( workspace );
568 if ( IDYES == MessageBox ( va("Are you sure you want to undo the checkout of the file '%s'?",workspace->GetFilename()), MB_YESNO|MB_ICONQUESTION) )
570 workspace->UndoCheckout ( );
574 case ID_GUIED_TOOLS_RELOADMATERIALS:
575 SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_WAIT) ) );
576 cmdSystem->BufferCommandText( CMD_EXEC_NOW, "reloadImages\n" );
577 cmdSystem->BufferCommandText( CMD_EXEC_NOW, "reloadMaterials\n" );
578 SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_ARROW) ) );
581 case ID_GUIED_EDIT_COPY:
582 assert ( workspace );
586 case ID_GUIED_EDIT_PASTE:
587 assert ( workspace );
588 workspace->Paste ( );
591 case ID_GUIED_HELP_ABOUT:
592 DialogBox ( GetInstance(), MAKEINTRESOURCE(IDD_GUIED_ABOUT), mMDIFrame, AboutDlg_WndProc );
595 case ID_GUIED_TOOLS_VIEWER:
602 mViewer = new rvGEViewer;
603 if ( !mViewer->Create ( mMDIFrame ) )
611 if ( !workspace->IsModified () || HandleCommand ( MAKELONG(ID_GUIED_FILE_SAVE,0), 0 ) )
613 mViewer->OpenFile ( workspace->GetFilename ( ) );
617 SetActiveWindow ( mViewer->GetWindow ( ) );
621 case ID_GUIED_ITEM_MAKESAMESIZEWIDTH:
622 assert ( workspace );
623 workspace->MakeSelectedSameSize ( true, false );
626 case ID_GUIED_ITEM_MAKESAMESIZEBOTH:
627 assert ( workspace );
628 workspace->MakeSelectedSameSize ( true, true );
631 case ID_GUIED_ITEM_MAKESAMESIZEHEIGHT:
632 assert ( workspace );
633 workspace->MakeSelectedSameSize ( false, true );
636 case ID_GUIED_ITEM_ALIGNLEFTS:
637 assert ( workspace );
638 workspace->AlignSelected ( rvGEWorkspace::ALIGN_LEFTS );
641 case ID_GUIED_ITEM_ALIGNCENTERS:
642 assert ( workspace );
643 workspace->AlignSelected ( rvGEWorkspace::ALIGN_CENTERS );
646 case ID_GUIED_ITEM_ALIGNRIGHTS:
647 assert ( workspace );
648 workspace->AlignSelected ( rvGEWorkspace::ALIGN_RIGHTS );
651 case ID_GUIED_ITEM_ALIGNTOPS:
652 assert ( workspace );
653 workspace->AlignSelected ( rvGEWorkspace::ALIGN_TOPS );
656 case ID_GUIED_ITEM_ALIGNMIDDLES:
657 assert ( workspace );
658 workspace->AlignSelected ( rvGEWorkspace::ALIGN_MIDDLES );
661 case ID_GUIED_ITEM_ALIGNBOTTOMS:
662 assert ( workspace );
663 workspace->AlignSelected ( rvGEWorkspace::ALIGN_BOTTOMS );
666 case ID_GUIED_ITEM_ARRANGESENDBACKWARD:
667 assert ( workspace );
668 workspace->SendSelectedBackward ( );
671 case ID_GUIED_ITEM_ARRANGESENDTOBACK:
672 assert ( workspace );
673 workspace->SendSelectedToBack( );
676 case ID_GUIED_ITEM_ARRANGEBRINGFORWARD:
677 assert ( workspace );
678 workspace->BringSelectedForward ( );
681 case ID_GUIED_ITEM_ARRANGEBRINGTOFRONT:
682 assert ( workspace );
683 workspace->BringSelectedToFront ( );
686 case ID_GUIED_ITEM_ARRANGEMAKECHILD:
687 assert ( workspace );
688 workspace->MakeSelectedAChild ( );
691 case ID_GUIED_ITEM_PROPERTIES:
692 assert ( workspace );
693 workspace->EditSelectedProperties ( );
696 case ID_GUIED_ITEM_SCRIPTS:
697 assert ( workspace );
698 workspace->EditSelectedScripts ( );
701 case ID_GUIED_ITEM_NEWWINDOWDEF:
702 assert ( workspace );
703 workspace->AddWindow ( rvGEWindowWrapper::WT_NORMAL );
706 case ID_GUIED_ITEM_NEWEDITDEF:
707 assert ( workspace );
708 workspace->AddWindow ( rvGEWindowWrapper::WT_EDIT );
711 case ID_GUIED_ITEM_NEWHTMLDEF:
712 assert ( workspace );
713 workspace->AddWindow ( rvGEWindowWrapper::WT_HTML );
716 case ID_GUIED_ITEM_NEWCHOICEDEF:
717 assert ( workspace );
718 workspace->AddWindow ( rvGEWindowWrapper::WT_CHOICE );
721 case ID_GUIED_ITEM_NEWSLIDERDEF:
722 assert ( workspace );
723 workspace->AddWindow ( rvGEWindowWrapper::WT_SLIDER );
726 case ID_GUIED_ITEM_NEWLISTDEF:
727 assert ( workspace );
728 workspace->AddWindow ( rvGEWindowWrapper::WT_LIST );
731 case ID_GUIED_ITEM_NEWBINDDEF:
732 assert ( workspace );
733 workspace->AddWindow ( rvGEWindowWrapper::WT_BIND );
736 case ID_GUIED_ITEM_NEWRENDERDEF:
737 assert ( workspace );
738 workspace->AddWindow ( rvGEWindowWrapper::WT_RENDER );
741 case ID_GUIED_WINDOW_TILE:
742 SendMessage ( mMDIClient, WM_MDITILE, 0, 0 );
745 case ID_GUIED_WINDOW_CASCADE:
746 SendMessage ( mMDIClient, WM_MDICASCADE, 0, 0 );
749 case ID_GUIED_VIEW_STATUSBAR:
753 mStatusBar.Show ( mOptions.GetStatusBarVisible()?false:true );
755 GetWindowRect ( mMDIFrame, &rWindow );
756 SendMessage ( mMDIFrame, WM_SIZE, 0, MAKELONG ( rWindow.right-rWindow.left, rWindow.bottom-rWindow.top ) );
760 case ID_GUIED_WINDOW_SHOWNAVIGATOR:
761 mNavigator.Show ( mOptions.GetNavigatorVisible()?false:true );
764 case ID_GUIED_WINDOW_SHOWPROPERTIES:
765 mProperties.Show ( mOptions.GetPropertiesVisible()?false:true );
768 case ID_GUIED_WINDOW_SHOWTRANSFORMER:
769 mTransformer.Show ( mOptions.GetTransformerVisible()?false:true );
772 case ID_GUIED_EDIT_DELETE:
773 assert ( workspace );
774 workspace->DeleteSelected ( );
777 case ID_GUIED_VIEW_HIDESELECTED:
778 assert ( workspace );
779 workspace->HideSelected ( );
782 case ID_GUIED_VIEW_UNHIDESELECTED:
783 assert ( workspace );
784 workspace->UnhideSelected ( );
787 case ID_GUIED_VIEW_SHOWHIDDEN:
788 assert ( workspace );
789 workspace->ShowHidden ( );
792 case ID_GUIED_EDIT_UNDO:
793 assert ( workspace );
794 workspace->GetModifierStack().Undo ( );
795 mNavigator.Update ( );
796 mTransformer.Update ( );
799 case ID_GUIED_EDIT_REDO:
800 assert ( workspace );
801 workspace->GetModifierStack().Redo ( );
802 mNavigator.Update ( );
803 mTransformer.Update ( );
806 case ID_GUIED_VIEW_OPTIONS:
807 GEOptionsDlg_DoModal ( mMDIFrame );
810 case ID_GUIED_VIEW_SHOWGRID:
811 mOptions.SetGridVisible ( mOptions.GetGridVisible()?false:true );
814 case ID_GUIED_VIEW_SNAPTOGRID:
815 mOptions.SetGridSnap ( mOptions.GetGridSnap ()?false:true );
818 case ID_GUIED_VIEW_ZOOMIN:
819 assert ( workspace );
820 workspace->ZoomIn ( );
823 case ID_GUIED_VIEW_ZOOMOUT:
824 assert ( workspace );
825 workspace->ZoomOut ( );
828 case ID_GUIED_FILE_EXIT:
829 DestroyWindow ( mMDIFrame );
832 case ID_GUIED_FILE_CLOSE:
835 assert ( workspace );
836 SendMessage ( active, WM_CLOSE, 0, 0 );
840 case ID_GUIED_FILE_NEW:
844 case ID_GUIED_FILE_SAVE:
845 assert ( workspace );
846 HandleCommandSave ( workspace, workspace->GetFilename ( ) );
849 case ID_GUIED_FILE_SAVEAS:
850 assert ( workspace );
851 HandleCommandSave ( workspace, NULL );
854 case ID_GUIED_FILE_OPEN:
857 char szFile[MAX_PATH] = "";
859 // Initialize OPENFILENAME
860 ZeroMemory(&ofn, sizeof(OPENFILENAME));
861 ofn.lStructSize = sizeof(OPENFILENAME);
862 ofn.hwndOwner = mMDIFrame;
863 ofn.lpstrFile = szFile;
864 ofn.nMaxFile = sizeof(szFile);
865 ofn.lpstrFilter = "GUI Files\0*.GUI\0All Files\0*.*\0";
866 ofn.nFilterIndex = 1;
867 ofn.lpstrFileTitle = NULL;
868 ofn.nMaxFileTitle = 0;
869 ofn.lpstrInitialDir = NULL;
870 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
872 // Display the Open dialog box.
873 if (GetOpenFileName(&ofn)==TRUE)
875 OpenFile ( ofn.lpstrFile );
886 rvGEApp::HandleInitMenu
888 Handles the initialization of the main menu
891 int rvGEApp::HandleInitMenu ( WPARAM wParam, LPARAM lParam )
893 int cMenuItems = GetMenuItemCount((HMENU)wParam);
897 rvGEWorkspace* workspace;
900 hmenu = (HMENU) wParam;
901 workspace = GetActiveWorkspace ( );
903 // Run through all the menu items in the menu and see if any of them need
904 // modification in any way
905 for (nPos = 0; nPos < cMenuItems; nPos++)
907 id = GetMenuItemID(hmenu, nPos);
910 // Handle popup menus too
913 HMENU sub = GetSubMenu ( hmenu, nPos );
916 HandleInitMenu ( (WPARAM) sub, 0 );
921 // Menu items that are completely unrelated to the workspace
924 case ID_GUIED_VIEW_STATUSBAR:
925 flags = MF_BYCOMMAND | (mOptions.GetStatusBarVisible()?MF_CHECKED:MF_UNCHECKED);
926 CheckMenuItem ( hmenu, id, flags );
929 case ID_GUIED_WINDOW_SHOWNAVIGATOR:
930 flags = MF_BYCOMMAND | (mOptions.GetNavigatorVisible()?MF_CHECKED:MF_UNCHECKED);
931 CheckMenuItem ( hmenu, id, flags );
934 case ID_GUIED_WINDOW_SHOWPROPERTIES:
935 flags = MF_BYCOMMAND | (mOptions.GetPropertiesVisible()?MF_CHECKED:MF_UNCHECKED);
936 CheckMenuItem ( hmenu, id, flags );
939 case ID_GUIED_WINDOW_SHOWTRANSFORMER:
940 flags = MF_BYCOMMAND | (mOptions.GetTransformerVisible()?MF_CHECKED:MF_UNCHECKED);
941 CheckMenuItem ( hmenu, id, flags );
945 // Handle the basic case where an item is disabled because
946 // there is no workspace available
951 case ID_GUIED_EDIT_UNDO:
952 case ID_GUIED_EDIT_REDO:
953 case ID_GUIED_VIEW_SHOWGRID:
954 case ID_GUIED_VIEW_SNAPTOGRID:
955 case ID_GUIED_VIEW_HIDESELECTED:
956 case ID_GUIED_VIEW_UNHIDESELECTED:
957 case ID_GUIED_EDIT_DELETE:
958 case ID_GUIED_WINDOW_TILE:
959 case ID_GUIED_WINDOW_CASCADE:
960 case ID_GUIED_ITEM_NEWWINDOWDEF:
961 case ID_GUIED_ITEM_NEWEDITDEF:
962 case ID_GUIED_ITEM_NEWHTMLDEF:
963 case ID_GUIED_ITEM_ARRANGEBRINGTOFRONT:
964 case ID_GUIED_ITEM_ARRANGEBRINGFORWARD:
965 case ID_GUIED_ITEM_ARRANGESENDTOBACK:
966 case ID_GUIED_ITEM_ARRANGESENDBACKWARD:
967 case ID_GUIED_ITEM_PROPERTIES:
968 case ID_GUIED_ITEM_SCRIPTS:
969 case ID_GUIED_VIEW_ZOOMIN:
970 case ID_GUIED_VIEW_ZOOMOUT:
971 case ID_GUIED_ITEM_ALIGNLEFTS:
972 case ID_GUIED_ITEM_ALIGNCENTERS:
973 case ID_GUIED_ITEM_ALIGNRIGHTS:
974 case ID_GUIED_ITEM_ALIGNBOTTOMS:
975 case ID_GUIED_ITEM_ALIGNMIDDLES:
976 case ID_GUIED_ITEM_ALIGNTOPS:
977 case ID_GUIED_ITEM_MAKESAMESIZEHEIGHT:
978 case ID_GUIED_ITEM_MAKESAMESIZEWIDTH:
979 case ID_GUIED_ITEM_MAKESAMESIZEBOTH:
980 case ID_GUIED_FILE_SAVE:
981 case ID_GUIED_FILE_SAVEAS:
982 case ID_GUIED_EDIT_COPY:
983 case ID_GUIED_EDIT_PASTE:
984 case ID_GUIED_ITEM_ARRANGEMAKECHILD:
985 case ID_GUIED_SOURCECONTROL_GETLATESTVERSION:
986 case ID_GUIED_SOURCECONTROL_CHECKIN:
987 case ID_GUIED_SOURCECONTROL_CHECKOUT:
988 case ID_GUIED_SOURCECONTROL_UNDOCHECKOUT:
989 case ID_GUIED_FILE_CLOSE:
990 EnableMenuItem ( hmenu, nPos, MF_GRAYED|MF_BYPOSITION );
999 // Undo is greyed out when there is noting to undo and the text is
1000 // modified to include the name of the modifier that will be undone
1001 case ID_GUIED_EDIT_UNDO:
1006 info.cbSize = sizeof(info);
1007 info.fMask = MIIM_STATE|MIIM_TYPE;
1008 info.fType = MFT_STRING;
1010 if ( !workspace->GetModifierStack().CanUndo ( ) )
1012 undo = "Undo\tCtrl+Z";
1013 info.fState = MFS_GRAYED;
1018 undo.Append ( workspace->GetModifierStack().GetUndoModifier()->GetName ( ) );
1019 undo.Append ( "\tCtrl+Z" );
1020 info.fState = MFS_ENABLED;
1023 info.dwTypeData = (LPSTR)undo.c_str();
1024 info.cch = undo.Length ( );
1026 SetMenuItemInfo ( hmenu, id, FALSE, &info );
1031 case ID_GUIED_EDIT_REDO:
1036 info.cbSize = sizeof(info);
1037 info.fMask = MIIM_STATE|MIIM_TYPE;
1038 info.fType = MFT_STRING;
1040 if ( !workspace || !workspace->GetModifierStack().CanRedo ( ) )
1042 undo = "Redo\tCtrl+Y";
1043 info.fState = MFS_GRAYED;
1048 undo.Append ( workspace->GetModifierStack().GetRedoModifier()->GetName ( ) );
1049 undo.Append ( "\tCtrl+Y" );
1050 info.fState = MFS_ENABLED;
1053 info.dwTypeData = (LPSTR)undo.c_str();
1054 info.cch = undo.Length ( );
1056 SetMenuItemInfo ( hmenu, id, FALSE, &info );
1061 case ID_GUIED_VIEW_SHOWGRID:
1062 flags = MF_BYCOMMAND | (mOptions.GetGridVisible()?MF_CHECKED:MF_UNCHECKED);
1063 CheckMenuItem ( hmenu, id, flags );
1066 case ID_GUIED_VIEW_SNAPTOGRID:
1067 flags = MF_BYCOMMAND | (mOptions.GetGridSnap()?MF_CHECKED:MF_UNCHECKED);
1068 CheckMenuItem ( hmenu, id, flags );
1071 // All menu items that are greyed out when there is no workspace
1072 case ID_GUIED_WINDOW_TILE:
1073 case ID_GUIED_WINDOW_CASCADE:
1074 case ID_GUIED_ITEM_NEWWINDOWDEF:
1075 case ID_GUIED_ITEM_NEWEDITDEF:
1076 case ID_GUIED_ITEM_NEWHTMLDEF:
1077 case ID_GUIED_VIEW_ZOOMIN:
1078 case ID_GUIED_VIEW_ZOOMOUT:
1079 case ID_GUIED_FILE_SAVE:
1080 case ID_GUIED_FILE_SAVEAS:
1081 case ID_GUIED_FILE_CLOSE:
1082 EnableMenuItem ( hmenu, nPos, MF_ENABLED|MF_BYPOSITION);
1085 // All menu items that are greyed out unless an item is selected
1086 case ID_GUIED_VIEW_HIDESELECTED:
1087 case ID_GUIED_VIEW_UNHIDESELECTED:
1088 case ID_GUIED_EDIT_DELETE:
1089 case ID_GUIED_EDIT_COPY:
1090 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|(workspace->GetSelectionMgr().Num()>0?MF_ENABLED:MF_GRAYED) );
1093 // Enable paste if the clipboard has something in it
1094 case ID_GUIED_EDIT_PASTE:
1095 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|(workspace->GetClipboard().Num()>0?MF_ENABLED:MF_GRAYED) );
1098 // All menu items that are greyed out unless a single item is selected
1099 case ID_GUIED_ITEM_ARRANGEBRINGTOFRONT:
1100 case ID_GUIED_ITEM_ARRANGEBRINGFORWARD:
1101 case ID_GUIED_ITEM_ARRANGESENDTOBACK:
1102 case ID_GUIED_ITEM_ARRANGESENDBACKWARD:
1103 case ID_GUIED_ITEM_PROPERTIES:
1104 case ID_GUIED_ITEM_SCRIPTS:
1105 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|(workspace->GetSelectionMgr().Num()==1?MF_ENABLED:MF_GRAYED) );
1108 // All menu items that are greyed out unless multiple itmes are selected
1109 case ID_GUIED_ITEM_ALIGNLEFTS:
1110 case ID_GUIED_ITEM_ALIGNCENTERS:
1111 case ID_GUIED_ITEM_ALIGNRIGHTS:
1112 case ID_GUIED_ITEM_ALIGNBOTTOMS:
1113 case ID_GUIED_ITEM_ALIGNMIDDLES:
1114 case ID_GUIED_ITEM_ALIGNTOPS:
1115 case ID_GUIED_ITEM_MAKESAMESIZEHEIGHT:
1116 case ID_GUIED_ITEM_MAKESAMESIZEBOTH:
1117 case ID_GUIED_ITEM_MAKESAMESIZEWIDTH:
1118 case ID_GUIED_ITEM_ARRANGEMAKECHILD:
1119 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|(workspace->GetSelectionMgr().Num()>1?MF_ENABLED:MF_GRAYED) );
1122 case ID_GUIED_SOURCECONTROL_CHECKIN:
1123 case ID_GUIED_SOURCECONTROL_UNDOCHECKOUT:
1124 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|((workspace->GetSourceControlState()==rvGEWorkspace::SCS_CHECKEDOUT)?MF_ENABLED:MF_GRAYED) );
1127 case ID_GUIED_SOURCECONTROL_CHECKOUT:
1128 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|((workspace->GetSourceControlState()==rvGEWorkspace::SCS_CHECKEDIN)?MF_ENABLED:MF_GRAYED) );
1143 Creates a new file and opens a window for it
1146 bool rvGEApp::NewFile ( void )
1148 rvGEWorkspace* workspace = new rvGEWorkspace ( this );
1149 if ( workspace->NewFile ( ) )
1153 child = CreateMDIWindow("QUAKE4_GUIEDITOR_CHILD_CLASS",
1155 WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_HSCROLL|WS_VSCROLL|WS_MAXIMIZE,
1164 ShowWindow ( child, SW_SHOW );
1174 Opens the given file and will fail if its already open or could not
1175 be opened for some reason
1178 bool rvGEApp::OpenFile ( const char* filename )
1181 bool result = false;
1184 // See if the file is already open and if so just make it active
1185 for ( i = 0; i < mWorkspaces.Num(); i ++ )
1187 if ( !idStr::Icmp ( mWorkspaces[i]->GetFilename(), filename ) )
1189 SendMessage ( mMDIClient, WM_MDIACTIVATE, (WPARAM)mWorkspaces[i]->GetWindow ( ), 0 );
1194 SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_WAIT ) ) );
1196 // Setup the default error.
1197 error = va("Failed to parse '%s'", filename );
1199 rvGEWorkspace* workspace = new rvGEWorkspace ( this );
1200 if ( workspace->LoadFile ( filename, &error ) )
1204 child = CreateMDIWindow("QUAKE4_GUIEDITOR_CHILD_CLASS",
1206 WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_HSCROLL|WS_VSCROLL|WS_MAXIMIZE,
1215 ShowWindow ( child, SW_SHOW );
1217 mOptions.AddRecentFile ( filename );
1218 UpdateRecentFiles ( );
1224 MessageBox ( error, MB_OK|MB_ICONERROR );
1227 SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_ARROW ) ) );
1234 rvGEApp::InitRecentFiles
1236 Finds the file menu and the location within it where the MRU should
1240 bool rvGEApp::InitRecentFiles ( void )
1245 mRecentFileMenu = GetSubMenu ( GetMenu(mMDIFrame), 0 );
1246 count = GetMenuItemCount ( mRecentFileMenu );
1248 for ( i = 0; i < count; i ++ )
1250 if ( GetMenuItemID ( mRecentFileMenu, i ) == ID_GUIED_FILE_MRU )
1252 mRecentFileInsertPos = i;
1253 DeleteMenu ( mRecentFileMenu, mRecentFileInsertPos, MF_BYPOSITION );
1263 rvGEApp::UpdateRecentFiles
1265 Updates the mru in the menu
1268 void rvGEApp::UpdateRecentFiles ( void )
1273 // Make sure everything is initialized
1274 if ( !mRecentFileMenu )
1276 InitRecentFiles ( );
1279 // Delete all the old recent files from the menu's
1280 for ( i = 0; i < rvGEOptions::MAX_MRU_SIZE; i ++ )
1282 DeleteMenu ( mRecentFileMenu, ID_GUIED_FILE_MRU1 + i, MF_BYCOMMAND );
1285 // Make sure there is a separator after the recent files
1286 if ( mOptions.GetRecentFileCount() )
1289 ZeroMemory ( &info, sizeof(info) );
1290 info.cbSize = sizeof(info);
1291 info.fMask = MIIM_FTYPE;
1292 GetMenuItemInfo ( mRecentFileMenu, mRecentFileInsertPos+1,TRUE, &info );
1293 if ( !(info.fType & MFT_SEPARATOR ) )
1295 InsertMenu ( mRecentFileMenu, mRecentFileInsertPos, MF_BYPOSITION|MF_SEPARATOR|MF_ENABLED, 0, NULL );
1299 // Add the recent files to the menu now
1300 for ( j = 0, i = mOptions.GetRecentFileCount ( ) - 1; i >= 0; i --, j++ )
1302 UINT id = ID_GUIED_FILE_MRU1 + j;
1303 idStr str = va("&%d ", j+1);
1304 str.Append ( mOptions.GetRecentFile ( i ) );
1305 InsertMenu ( mRecentFileMenu, mRecentFileInsertPos+j+1, MF_BYPOSITION|MF_STRING|MF_ENABLED, id, str );
1311 rvGEApp::CloseViewer
1313 Closes the gui viewer
1316 void rvGEApp::CloseViewer ( void )
1323 mViewer->Destroy ( );
1330 rvGEApp::ToolWindowActivate
1332 Handles the nc activate message for all tool windows
1335 int rvGEApp::ToolWindowActivate ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
1341 keepActive = ( wParam != 0 );
1344 for ( i = 0; i < mToolWindows.Num (); i ++ )
1346 if ( (HWND)lParam == mToolWindows[i] )
1356 return DefWindowProc ( hwnd, WM_NCACTIVATE, keepActive, 0 );
1361 for ( i = 0; i < mToolWindows.Num(); i ++ )
1363 if ( mToolWindows[i] != hwnd && mToolWindows[i] != (HWND) lParam )
1365 SendMessage ( mToolWindows[i], WM_NCACTIVATE, keepActive, (LONG)-1 );
1370 return DefWindowProc ( hwnd, WM_NCACTIVATE, keepActive, lParam );
1377 Displays a modal message box
1380 int rvGEApp::MessageBox ( const char* text, int flags )
1382 return ::MessageBox ( mMDIFrame, text, "Quake 4 GUI Editor", flags );