]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/guied/GEApp.cpp
hello world
[icculus/iodoom3.git] / neo / tools / guied / GEApp.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
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.
13
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.
18
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/>.
21
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.
23
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.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include <io.h>
33
34 #include "../../sys/win32/rc/guied_resource.h"
35 #include "../../ui/DeviceContext.h"
36
37 #include "GEApp.h"
38 #include "GEOptionsDlg.h"
39 #include "GEViewer.h"
40
41 static const int IDM_WINDOWCHILD        = 1000;
42 static const int ID_GUIED_FILE_MRU1 = 10000;
43
44 static INT_PTR CALLBACK AboutDlg_WndProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
45 {
46         switch ( msg )
47         {
48                 case WM_COMMAND:
49                         EndDialog ( hwnd, 1 );
50                         break;                  
51         }
52         
53         return FALSE;
54 }
55
56
57 rvGEApp::rvGEApp ( )
58 {
59         mMDIFrame                        = NULL;
60         mMDIClient                       = NULL;
61         mRecentFileMenu          = NULL;
62         mViewer                          = NULL;
63         mRecentFileInsertPos = 0;
64 }
65
66 rvGEApp::~rvGEApp ( )
67 {
68         DestroyAcceleratorTable ( mAccelerators );
69 }
70
71 /*
72 ================
73 rvGEApp::Initialize
74
75 Initialize the gui editor application
76 ================
77 */
78 bool rvGEApp::Initialize ( void )
79 {
80         mOptions.Init();
81
82         // Mutually exclusive
83         com_editors = EDITOR_GUI;
84
85         Sys_GrabMouseCursor( false );
86         
87         // Load the options
88         mOptions.Load ( );      
89
90         mInstance = win32.hInstance;
91
92         // Create the accelerators
93         mAccelerators = LoadAccelerators ( mInstance, MAKEINTRESOURCE(IDR_GUIED_ACCELERATORS) );
94
95         // Register the window classes for the main frame and the mdi child window      
96         WNDCLASSEX wndClass;
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 );
106
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 );
113         
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 );
120
121         if ( !mMDIFrame )
122         {
123                 return false;
124         }
125
126         SetClassLong( mMDIFrame, GCL_HICON, ( LONG )LoadIcon( win32.hInstance, MAKEINTRESOURCE( IDI_GUIED ) ) );
127         
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, 
134                                                                 0, 0, 1000, 1000, 
135                                                                 mMDIFrame, NULL, 
136                                                                 mInstance, &ccs );
137
138         if ( !mMDIClient )
139         {
140                 DestroyWindow ( mMDIFrame );
141                 return false;
142         }
143
144         // hide the doom window by default
145         ::ShowWindow ( win32.hWnd, SW_HIDE );
146         
147         // Show both windows
148         mOptions.GetWindowPlacement ( "mdiframe", mMDIFrame );
149         ShowWindow ( mMDIFrame, SW_SHOW ); 
150         UpdateWindow ( mMDIFrame );
151
152         ShowWindow ( mMDIClient, SW_SHOW );
153         UpdateWindow ( mMDIClient );
154         
155         return true;
156 }
157
158
159 /*
160 ================
161 rvGEApp::GetActiveWorkspace
162
163 Retrieves the workspace pointer for the active workspace.  If there is no active
164 workspace then it will return NULL
165 ================
166 */
167 rvGEWorkspace* rvGEApp::GetActiveWorkspace ( HWND* ret )
168 {
169     rvGEWorkspace*      workspace;
170     HWND                        active;
171         
172         workspace = NULL;
173         active    = (HWND)SendMessage ( mMDIClient, WM_MDIGETACTIVE, 0, NULL );
174
175         // Return the window handle if requested
176         if ( ret )
177         {
178                 *ret = active;
179         }
180
181         if ( !active )
182         {
183                 return NULL;
184         }
185         
186         return rvGEWorkspace::GetWorkspace ( active );
187 }
188
189 /*
190 ================
191 rvGEApp::TranslateAccelerator
192
193 Translate any accelerators destined for this window
194 ================
195 */
196 bool rvGEApp::TranslateAccelerator ( LPMSG msg )
197 {
198         HWND focus;
199
200         if ( msg->message == WM_SYSCHAR )
201         {
202                 SetFocus ( GetMDIClient ( ) );  
203                 msg->hwnd = GetMDIClient ( );   
204         }
205
206         if ( mViewer )
207         {
208                 return false;
209         }
210
211         focus = GetActiveWindow ( );
212
213         // Only use accelerators when on the main window or navigator window
214         if ( focus == mMDIClient || focus == mMDIFrame ||
215                  focus == GetNavigator().GetWindow ( ) )
216         {
217                 if ( ::TranslateAccelerator ( mMDIFrame, mAccelerators, msg ) )
218                 {
219                         return true;
220                 }
221         }
222         
223         if ( TranslateMDISysAccel ( mMDIClient, msg ) )
224         {
225                 return true;
226         }
227         
228         return false;
229 }
230
231 /*
232 ================
233 rvGEApp::RunFrame
234
235 Runs the current frame which causes the active window to be redrawn
236 ================
237 */
238 void rvGEApp::RunFrame ( void )
239 {
240         HWND                    wnd;
241         rvGEWorkspace*  workspace = GetActiveWorkspace ( &wnd );
242
243         if ( workspace )
244         {               
245                 // Render the workspace using a temp DC
246                 HDC hDC = GetDC ( wnd );                
247                 workspace->Render ( hDC );              
248                 ReleaseDC ( wnd, hDC );                         
249                 
250                 if ( mViewer )
251                 {
252                         mViewer->RunFrame ( );
253                 }
254         }
255 }
256
257 /*
258 ================
259 rvGEApp::FrameWndProc
260
261 Main frame window procedure
262 ================
263 */
264 LRESULT CALLBACK rvGEApp::FrameWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
265 {
266         rvGEApp* app = (rvGEApp*) GetWindowLong ( hWnd, GWL_USERDATA );
267
268         switch ( uMsg )
269         {               
270                 case WM_SIZE:
271                 {
272                         RECT rStatus;
273                         RECT rClient;
274
275                         // Tell the status bar to resize                        
276                         app->mStatusBar.Resize ( LOWORD(lParam), HIWORD(lParam) );
277                                 
278                         // Calculate the new client window rectangle (minus the status bar)
279                         GetWindowRect ( app->mStatusBar.GetWindow ( ), &rStatus );
280                         GetClientRect ( hWnd, &rClient );
281
282                         if ( app->mOptions.GetStatusBarVisible ( ) )
283                         {
284                                 rClient.bottom -= (rStatus.bottom-rStatus.top);
285                         }
286                         MoveWindow ( app->mMDIClient, 0, 0, rClient.right-rClient.left, rClient.bottom-rClient.top, FALSE );
287                         
288                         return 0;
289                 }
290                 
291                 case WM_ENABLE:
292                 {       
293                         int i;
294
295                     // Synchronise all toolwindows to the same state.
296                         for(i = 0; i < app->mToolWindows.Num(); i++)
297                         {
298                         if(app->mToolWindows[i] != hWnd)
299                                 {
300                                         EnableWindow(app->mToolWindows[i], wParam);
301                                 }
302                     }
303                     break;
304                 }               
305
306                 case WM_NCACTIVATE:
307                         return app->ToolWindowActivate ( hWnd, uMsg, wParam, lParam );
308
309                 case WM_ACTIVATE:
310                         common->ActivateTool( LOWORD( wParam ) != WA_INACTIVE );
311                         break;
312
313                 case WM_INITMENUPOPUP:
314                         app->HandleInitMenu ( wParam, lParam  );
315                         break;
316
317                 case WM_CLOSE:                  
318                         while ( app->mWorkspaces.Num ( ) )
319                         {
320                                 SendMessage ( app->mWorkspaces[0]->GetWindow ( ), WM_CLOSE, 0, 0 );
321                         }
322                         break;
323
324                 case WM_DESTROY:
325                         app->mOptions.SetWindowPlacement ( "mdiframe", hWnd );
326                         app->mOptions.Save ( );                 
327                         ExitProcess(0);
328                         break;                  
329
330                 case WM_COMMAND:
331                 {
332                         int result;
333                         assert ( app );
334                         result = app->HandleCommand ( wParam, lParam );
335                         if ( -1 != result )
336                         {
337                                 return result;
338                         }                       
339                         break;
340                 }
341
342                 case WM_CREATE:
343                 {       
344                         LPCREATESTRUCT          cs;
345                                                                                 
346                         cs = (LPCREATESTRUCT) lParam;
347                         app = (rvGEApp*)cs->lpCreateParams;
348
349                         assert ( app );
350                         
351                         SetWindowLong ( hWnd, GWL_USERDATA, (LONG)app );
352
353                         app->mMDIFrame = hWnd;
354                         
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 ( ) );
361
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 ( ) );
367                         
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 );                 
371
372                         break;
373                 }
374         }
375
376         return DefFrameProc ( hWnd, app?app->mMDIClient:NULL, uMsg, wParam, lParam );
377 }
378
379 /*
380 ================
381 rvGEApp::MDIChildProc
382
383 MDI Child window procedure
384 ================
385 */
386 LRESULT CALLBACK rvGEApp::MDIChildProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
387 {
388         rvGEWorkspace* workspace = (rvGEWorkspace*)GetWindowLong ( hWnd, GWL_USERDATA );        
389
390         // Give the active workspace a chance to play with it
391         if ( workspace )
392         {
393                 workspace->HandleMessage ( uMsg, wParam, lParam );
394         }
395
396         switch ( uMsg )
397         {
398                 case WM_CLOSE:
399                         workspace->GetApplication ( )->mWorkspaces.Remove ( workspace );
400                         break;
401
402                 case WM_CREATE:
403                 {       
404                         LPMDICREATESTRUCT       mdics;
405                         LPCREATESTRUCT          cs;
406                                         
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;
411                         
412                         // Attach the workspace to the window
413                         workspace = (rvGEWorkspace*) mdics->lParam;
414                         workspace->Attach ( hWnd );                     
415
416                         workspace->GetApplication ( )->mWorkspaces.Append ( workspace );                                
417                                 
418                         break;
419                 }
420
421                 case WM_MDIACTIVATE:
422                         assert ( workspace );
423                         if ( (HWND)lParam == hWnd )
424                         {                               
425                                 workspace->GetApplication ( )->GetNavigator().SetWorkspace(workspace);
426                                 workspace->GetApplication ( )->GetTransformer().SetWorkspace(workspace);
427                                 workspace->GetApplication ( )->GetProperties().SetWorkspace(workspace);
428                                 gApp.GetStatusBar ( ).SetSimple ( false );
429                         }
430                         else if ( lParam == NULL )
431                         {
432                                 gApp.GetStatusBar ( ).SetSimple ( true );
433                         }
434                         break;          
435
436                 case WM_DESTROY:
437                         assert ( workspace );
438                         workspace->Detach ( );
439                         delete workspace;
440                         break;
441
442                 case WM_SETCURSOR:
443                         return 1;
444
445                 case WM_ERASEBKGND:
446                         return TRUE;
447
448                 case WM_PAINT:
449                 {
450                         HDC                     dc;
451                         PAINTSTRUCT     ps;
452                         
453                         dc = BeginPaint(hWnd, &ps); 
454                         
455                         if ( workspace )
456                         {
457                                 workspace->Render ( dc );
458                         }
459                         
460             EndPaint(hWnd, &ps); 
461            
462                         break;
463                 }
464         }
465         
466         return DefMDIChildProc ( hWnd, uMsg, wParam, lParam );
467 }
468
469 /*
470 ================
471 rvGEApp::HandleCommandSave
472
473 Handles the ID_GUIED_FILE_SAVE and ID_GUIED_FILE_SAVEAS commands
474 ================
475 */
476 void rvGEApp::HandleCommandSave ( rvGEWorkspace* workspace, const char* filename )
477 {
478         idStr realFilename;
479         
480         // See if we need to browse for a filename
481         if ( workspace->IsNew ( ) || filename == NULL )
482         {
483                 OPENFILENAME ofn;
484                 char             szFile[MAX_PATH];
485
486                 strcpy ( szFile, workspace->GetFilename ( ) );
487
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;
497
498                 // Display the save dialog box. 
499                 if ( !GetSaveFileName(&ofn) ) 
500                 {
501                         return;
502                 }
503
504                 realFilename = ofn.lpstrFile;
505                 realFilename.StripFileExtension ( );
506                 realFilename.Append ( ".gui" );
507
508                 // If the file already exists then warn about overwriting it
509                 if ( _taccess ( realFilename, 0 ) == 0 )
510                 {
511                         if ( IDNO == MessageBox ( va("File '%s' already exists. Do you want to replace it?", realFilename.c_str()), MB_YESNO|MB_ICONQUESTION ) )
512                         {
513                                 return;
514                         }
515                 }
516         }
517         else
518         {
519                 realFilename = filename;
520         }       
521
522         // Now performe the file save
523         if ( workspace->SaveFile ( realFilename ) )
524         {
525                 mOptions.AddRecentFile ( workspace->GetFilename ( ) );
526                 UpdateRecentFiles ( );
527         }
528         else
529         {
530                 MessageBox ( va("Could not write file '%s'", workspace->GetFilename()), MB_OK|MB_ICONERROR );
531         }
532 }
533
534 /*
535 ================
536 rvGEApp::HandleCommand
537
538 Handles the WM_COMMAND message
539 ================
540 */
541 int rvGEApp::HandleCommand ( WPARAM wParam, LPARAM lParam )
542 {
543         HWND               active;
544         rvGEWorkspace* workspace = GetActiveWorkspace ( &active );
545
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 )
548         {
549                 OpenFile ( mOptions.GetRecentFile ( mOptions.GetRecentFileCount() - (LOWORD(wParam)-ID_GUIED_FILE_MRU1) - 1 ) );
550                 return 0;
551         }
552                                         
553         switch ( LOWORD ( wParam ) )
554         {               
555                 case ID_GUIED_SOURCECONTROL_CHECKIN:
556                         assert ( workspace );
557                         HandleCommandSave ( workspace, workspace->GetFilename ( ) );
558                         workspace->CheckIn ( );
559                         break;
560                         
561                 case ID_GUIED_SOURCECONTROL_CHECKOUT:
562                         assert ( workspace );
563                         workspace->CheckOut ( );
564                         break;
565
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) )
569                         {
570                                 workspace->UndoCheckout ( );
571                         }
572                         break;
573                         
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) ) );
579                         break;
580                         
581                 case ID_GUIED_EDIT_COPY:
582                         assert ( workspace );
583                         workspace->Copy  ( );
584                         break;
585
586                 case ID_GUIED_EDIT_PASTE:
587                         assert ( workspace );
588                         workspace->Paste  ( );
589                         break;
590         
591                 case ID_GUIED_HELP_ABOUT:
592                         DialogBox ( GetInstance(), MAKEINTRESOURCE(IDD_GUIED_ABOUT), mMDIFrame, AboutDlg_WndProc );
593                         break;
594         
595                 case ID_GUIED_TOOLS_VIEWER:
596                 {
597                         if ( mViewer )
598                         {
599                                 break;
600                         }
601                         
602                         mViewer = new rvGEViewer;
603                         if ( !mViewer->Create ( mMDIFrame ) )
604                         {
605                                 delete mViewer;
606                                 mViewer = NULL;
607                         }
608                                                 
609                         if ( workspace )
610                         {                               
611                                 if ( !workspace->IsModified () || HandleCommand ( MAKELONG(ID_GUIED_FILE_SAVE,0), 0 ) )
612                                 {
613                                         mViewer->OpenFile ( workspace->GetFilename ( ) );
614                                 }
615                         }
616                         
617                         SetActiveWindow ( mViewer->GetWindow ( ) );
618                         break;
619                 }
620                 
621                 case ID_GUIED_ITEM_MAKESAMESIZEWIDTH:
622                         assert ( workspace );
623                         workspace->MakeSelectedSameSize ( true, false );
624                         break;
625
626                 case ID_GUIED_ITEM_MAKESAMESIZEBOTH:
627                         assert ( workspace );
628                         workspace->MakeSelectedSameSize ( true, true );
629                         break;
630
631                 case ID_GUIED_ITEM_MAKESAMESIZEHEIGHT:
632                         assert ( workspace );
633                         workspace->MakeSelectedSameSize ( false, true );
634                         break;
635         
636                 case ID_GUIED_ITEM_ALIGNLEFTS:
637                         assert ( workspace );
638                         workspace->AlignSelected ( rvGEWorkspace::ALIGN_LEFTS );
639                         break;
640
641                 case ID_GUIED_ITEM_ALIGNCENTERS:
642                         assert ( workspace );
643                         workspace->AlignSelected ( rvGEWorkspace::ALIGN_CENTERS );
644                         break;
645
646                 case ID_GUIED_ITEM_ALIGNRIGHTS:
647                         assert ( workspace );
648                         workspace->AlignSelected ( rvGEWorkspace::ALIGN_RIGHTS );
649                         break;
650
651                 case ID_GUIED_ITEM_ALIGNTOPS:
652                         assert ( workspace );
653                         workspace->AlignSelected ( rvGEWorkspace::ALIGN_TOPS );
654                         break;
655
656                 case ID_GUIED_ITEM_ALIGNMIDDLES:
657                         assert ( workspace );
658                         workspace->AlignSelected ( rvGEWorkspace::ALIGN_MIDDLES );
659                         break;
660
661                 case ID_GUIED_ITEM_ALIGNBOTTOMS:
662                         assert ( workspace );
663                         workspace->AlignSelected ( rvGEWorkspace::ALIGN_BOTTOMS );
664                         break;
665                         
666                 case ID_GUIED_ITEM_ARRANGESENDBACKWARD:
667                         assert ( workspace );
668                         workspace->SendSelectedBackward ( );
669                         break;                  
670
671                 case ID_GUIED_ITEM_ARRANGESENDTOBACK:
672                         assert ( workspace );
673                         workspace->SendSelectedToBack( );
674                         break;                  
675
676                 case ID_GUIED_ITEM_ARRANGEBRINGFORWARD:
677                         assert ( workspace );
678                         workspace->BringSelectedForward ( );
679                         break;                  
680
681                 case ID_GUIED_ITEM_ARRANGEBRINGTOFRONT:
682                         assert ( workspace );
683                         workspace->BringSelectedToFront ( );
684                         break;                  
685                         
686                 case ID_GUIED_ITEM_ARRANGEMAKECHILD:
687                         assert ( workspace );
688                         workspace->MakeSelectedAChild ( );
689                         break;
690         
691                 case ID_GUIED_ITEM_PROPERTIES:
692                         assert ( workspace );
693                         workspace->EditSelectedProperties ( );
694                         break;
695
696                 case ID_GUIED_ITEM_SCRIPTS:
697                         assert ( workspace );
698                         workspace->EditSelectedScripts ( );
699                         break;
700                         
701                 case ID_GUIED_ITEM_NEWWINDOWDEF:
702                         assert ( workspace );
703                         workspace->AddWindow ( rvGEWindowWrapper::WT_NORMAL );
704                         break;
705
706                 case ID_GUIED_ITEM_NEWEDITDEF:
707                         assert ( workspace );
708                         workspace->AddWindow ( rvGEWindowWrapper::WT_EDIT );
709                         break;
710
711                 case ID_GUIED_ITEM_NEWHTMLDEF:
712                         assert ( workspace );
713                         workspace->AddWindow ( rvGEWindowWrapper::WT_HTML );
714                         break;
715
716                 case ID_GUIED_ITEM_NEWCHOICEDEF:
717                         assert ( workspace );
718                         workspace->AddWindow ( rvGEWindowWrapper::WT_CHOICE );
719                         break;
720
721                 case ID_GUIED_ITEM_NEWSLIDERDEF:
722                         assert ( workspace );
723                         workspace->AddWindow ( rvGEWindowWrapper::WT_SLIDER );
724                         break;
725
726                 case ID_GUIED_ITEM_NEWLISTDEF:
727                         assert ( workspace );
728                         workspace->AddWindow ( rvGEWindowWrapper::WT_LIST );
729                         break;
730
731                 case ID_GUIED_ITEM_NEWBINDDEF:
732                         assert ( workspace );
733                         workspace->AddWindow ( rvGEWindowWrapper::WT_BIND );
734                         break;
735
736                 case ID_GUIED_ITEM_NEWRENDERDEF:
737                         assert ( workspace );
738                         workspace->AddWindow ( rvGEWindowWrapper::WT_RENDER );
739                         break;
740         
741                 case ID_GUIED_WINDOW_TILE:
742                         SendMessage ( mMDIClient, WM_MDITILE, 0, 0 );
743                         break;  
744
745                 case ID_GUIED_WINDOW_CASCADE:
746                         SendMessage ( mMDIClient, WM_MDICASCADE, 0, 0 );
747                         break;  
748
749                 case ID_GUIED_VIEW_STATUSBAR:
750                 {
751                         RECT rWindow;
752                         
753                         mStatusBar.Show ( mOptions.GetStatusBarVisible()?false:true );
754                         
755                         GetWindowRect ( mMDIFrame, &rWindow );
756                         SendMessage ( mMDIFrame, WM_SIZE, 0, MAKELONG ( rWindow.right-rWindow.left, rWindow.bottom-rWindow.top ) );                     
757                         break;
758                 }
759
760                 case ID_GUIED_WINDOW_SHOWNAVIGATOR:
761                         mNavigator.Show ( mOptions.GetNavigatorVisible()?false:true );
762                         break;                                  
763                         
764                 case ID_GUIED_WINDOW_SHOWPROPERTIES:
765                         mProperties.Show ( mOptions.GetPropertiesVisible()?false:true );
766                         break;
767                         
768                 case ID_GUIED_WINDOW_SHOWTRANSFORMER:
769                         mTransformer.Show ( mOptions.GetTransformerVisible()?false:true  );
770                         break;                                  
771                         
772                 case ID_GUIED_EDIT_DELETE:
773                         assert ( workspace );
774                         workspace->DeleteSelected ( );
775                         break;
776
777                 case ID_GUIED_VIEW_HIDESELECTED:
778                         assert ( workspace );
779                         workspace->HideSelected ( );
780                         break;
781
782                 case ID_GUIED_VIEW_UNHIDESELECTED:
783                         assert ( workspace );
784                         workspace->UnhideSelected ( );
785                         break;
786                 
787                 case ID_GUIED_VIEW_SHOWHIDDEN:
788                         assert ( workspace );
789                         workspace->ShowHidden ( );
790                         break;
791                         
792                 case ID_GUIED_EDIT_UNDO:
793                         assert ( workspace );
794                         workspace->GetModifierStack().Undo ( );
795                         mNavigator.Update ( );
796                         mTransformer.Update ( );
797                         break;
798
799                 case ID_GUIED_EDIT_REDO:
800                         assert ( workspace );
801                         workspace->GetModifierStack().Redo ( );
802                         mNavigator.Update ( );
803                         mTransformer.Update ( );
804                         break;
805         
806                 case ID_GUIED_VIEW_OPTIONS:
807                         GEOptionsDlg_DoModal ( mMDIFrame );
808                         break;
809         
810                 case ID_GUIED_VIEW_SHOWGRID:
811                         mOptions.SetGridVisible ( mOptions.GetGridVisible()?false:true );                               
812                         break;
813
814                 case ID_GUIED_VIEW_SNAPTOGRID:
815                         mOptions.SetGridSnap ( mOptions.GetGridSnap ()?false:true );                            
816                         break;
817         
818                 case ID_GUIED_VIEW_ZOOMIN:
819                         assert ( workspace );
820                         workspace->ZoomIn ( );
821                         break;
822                         
823                 case ID_GUIED_VIEW_ZOOMOUT:
824                         assert ( workspace );
825                         workspace->ZoomOut ( );
826                         break;
827         
828                 case ID_GUIED_FILE_EXIT:
829                         DestroyWindow ( mMDIFrame );
830                         break;
831
832                 case ID_GUIED_FILE_CLOSE:
833                         if ( active )
834                         {
835                                 assert ( workspace );
836                                 SendMessage ( active, WM_CLOSE, 0, 0 );
837                         }
838                         break;
839                         
840                 case ID_GUIED_FILE_NEW:
841                         NewFile ( );
842                         break;
843
844                 case ID_GUIED_FILE_SAVE:
845                         assert ( workspace );
846                         HandleCommandSave ( workspace, workspace->GetFilename ( ) );
847                         break;
848
849                 case ID_GUIED_FILE_SAVEAS:
850                         assert ( workspace );
851                         HandleCommandSave ( workspace, NULL );
852                         break;                  
853                         
854                 case ID_GUIED_FILE_OPEN:
855                 {
856                         OPENFILENAME ofn;
857                         char             szFile[MAX_PATH] = "";
858
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;
871
872                         // Display the Open dialog box. 
873                         if (GetOpenFileName(&ofn)==TRUE) 
874                         {                       
875                                 OpenFile ( ofn.lpstrFile );
876                         }
877                         break;
878                 }                       
879         }
880         
881         return -1;
882 }
883
884 /*
885 ================
886 rvGEApp::HandleInitMenu
887
888 Handles the initialization of the main menu
889 ================
890 */
891 int rvGEApp::HandleInitMenu ( WPARAM wParam, LPARAM lParam ) 
892
893     int                         cMenuItems = GetMenuItemCount((HMENU)wParam); 
894     int                         nPos; 
895     int                         id; 
896     UINT                        flags; 
897     rvGEWorkspace*      workspace;
898     HMENU                       hmenu;
899  
900         hmenu     = (HMENU) wParam;
901         workspace = GetActiveWorkspace ( );
902
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++) 
906     { 
907         id    = GetMenuItemID(hmenu, nPos); 
908         flags = 0;
909  
910                 // Handle popup menus too
911                 if ( id < 0 )
912                 {
913                         HMENU sub = GetSubMenu ( hmenu, nPos );
914                         if ( sub )
915                         {
916                                 HandleInitMenu ( (WPARAM) sub, 0 );
917                                 continue;
918                         }
919                 }
920         
921                 // Menu items that are completely unrelated to the workspace
922                 switch ( id )
923                 {
924                         case ID_GUIED_VIEW_STATUSBAR:
925                                 flags = MF_BYCOMMAND | (mOptions.GetStatusBarVisible()?MF_CHECKED:MF_UNCHECKED);
926                                 CheckMenuItem ( hmenu, id, flags );
927                                 break;                          
928
929                         case ID_GUIED_WINDOW_SHOWNAVIGATOR:
930                                 flags = MF_BYCOMMAND | (mOptions.GetNavigatorVisible()?MF_CHECKED:MF_UNCHECKED);
931                                 CheckMenuItem ( hmenu, id, flags );
932                                 break;                          
933                         
934                         case ID_GUIED_WINDOW_SHOWPROPERTIES:
935                                 flags = MF_BYCOMMAND | (mOptions.GetPropertiesVisible()?MF_CHECKED:MF_UNCHECKED);
936                                 CheckMenuItem ( hmenu, id, flags );
937                                 break;                          
938
939                         case ID_GUIED_WINDOW_SHOWTRANSFORMER:
940                                 flags = MF_BYCOMMAND | (mOptions.GetTransformerVisible()?MF_CHECKED:MF_UNCHECKED);
941                                 CheckMenuItem ( hmenu, id, flags );
942                                 break;                          
943                 }
944  
945                 // Handle the basic case where an item is disabled because
946                 // there is no workspace available
947                 if ( !workspace )
948                 {
949                         switch ( id )
950                         {
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 );
991                                         break;
992                         }
993
994                         continue;
995                 }
996
997         switch (id) 
998         { 
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:
1002                         {
1003                                 MENUITEMINFO info;
1004                                 idStr            undo;
1005
1006                                 info.cbSize = sizeof(info);
1007                                 info.fMask = MIIM_STATE|MIIM_TYPE;
1008                                 info.fType = MFT_STRING;
1009                                 
1010                                 if ( !workspace->GetModifierStack().CanUndo ( ) )
1011                                 {                               
1012                                         undo = "Undo\tCtrl+Z";
1013                                         info.fState = MFS_GRAYED;
1014                                 }
1015                                 else
1016                                 {
1017                                         undo = "Undo ";
1018                                         undo.Append ( workspace->GetModifierStack().GetUndoModifier()->GetName ( ) );
1019                                         undo.Append ( "\tCtrl+Z" );
1020                                         info.fState = MFS_ENABLED;
1021                                 }
1022
1023                                 info.dwTypeData = (LPSTR)undo.c_str();
1024                                 info.cch = undo.Length ( );
1025                                                                         
1026                                 SetMenuItemInfo ( hmenu, id, FALSE, &info );
1027
1028                                 break;
1029                         }
1030
1031                         case ID_GUIED_EDIT_REDO:
1032                         {
1033                                 MENUITEMINFO info;
1034                                 idStr            undo;
1035
1036                                 info.cbSize = sizeof(info);
1037                                 info.fMask = MIIM_STATE|MIIM_TYPE;
1038                                 info.fType = MFT_STRING;
1039                                 
1040                                 if ( !workspace || !workspace->GetModifierStack().CanRedo ( ) )
1041                                 {                               
1042                                         undo = "Redo\tCtrl+Y";
1043                                         info.fState = MFS_GRAYED;
1044                                 }
1045                                 else
1046                                 {
1047                                         undo = "Redo ";
1048                                         undo.Append ( workspace->GetModifierStack().GetRedoModifier()->GetName ( ) );
1049                                         undo.Append ( "\tCtrl+Y" );
1050                                         info.fState = MFS_ENABLED;
1051                                 }
1052
1053                                 info.dwTypeData = (LPSTR)undo.c_str();
1054                                 info.cch = undo.Length ( );
1055                                                                         
1056                                 SetMenuItemInfo ( hmenu, id, FALSE, &info );
1057
1058                                 break;
1059                         }
1060                                 
1061                         case ID_GUIED_VIEW_SHOWGRID:
1062                                 flags = MF_BYCOMMAND | (mOptions.GetGridVisible()?MF_CHECKED:MF_UNCHECKED);
1063                                 CheckMenuItem ( hmenu, id, flags );
1064                                 break;                          
1065
1066                         case ID_GUIED_VIEW_SNAPTOGRID:
1067                                 flags = MF_BYCOMMAND | (mOptions.GetGridSnap()?MF_CHECKED:MF_UNCHECKED);
1068                                 CheckMenuItem ( hmenu, id, flags );
1069                                 break;                          
1070                         
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);
1083                                 break;
1084
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) );
1091                                 break;
1092
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) );
1096                                 break;
1097                         
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) );
1106                                 break;
1107
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) );
1120                                 break;
1121
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) );
1125                                 break;
1126
1127                         case ID_GUIED_SOURCECONTROL_CHECKOUT:
1128                                 EnableMenuItem ( hmenu, nPos, MF_BYPOSITION|((workspace->GetSourceControlState()==rvGEWorkspace::SCS_CHECKEDIN)?MF_ENABLED:MF_GRAYED) );
1129                                 break;
1130                         
1131                         default:
1132                                 continue;
1133                 }                               
1134         }
1135         
1136         return 0;
1137
1138
1139 /*
1140 ================
1141 rvGEApp::NewFile
1142
1143 Creates a new file and opens a window for it
1144 ================
1145 */
1146 bool rvGEApp::NewFile ( void )
1147 {
1148         rvGEWorkspace* workspace = new rvGEWorkspace ( this );
1149         if ( workspace->NewFile ( ) )
1150         {
1151                 HWND child;
1152                 
1153                 child = CreateMDIWindow("QUAKE4_GUIEDITOR_CHILD_CLASS",
1154                                                                 "Untitled.gui",
1155                                                                 WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_HSCROLL|WS_VSCROLL|WS_MAXIMIZE,
1156                                                                 CW_USEDEFAULT,
1157                                                                 CW_USEDEFAULT,
1158                                                                 640,
1159                                                                 480,
1160                                                                 mMDIClient,
1161                                                                 mInstance,
1162                                                                 (LONG)workspace );
1163                                                                                                                 
1164                 ShowWindow ( child, SW_SHOW );
1165         }
1166
1167         return true;
1168 }
1169
1170 /*
1171 ================
1172 rvGEApp::OpenFile
1173
1174 Opens the given file and will fail if its already open or could not
1175 be opened for some reason
1176 ================
1177 */
1178 bool rvGEApp::OpenFile ( const char* filename )
1179 {
1180         int i;
1181         bool result = false;
1182         idStr error;
1183
1184         // See if the file is already open and if so just make it active
1185         for ( i = 0; i < mWorkspaces.Num(); i ++ )
1186         {
1187                 if ( !idStr::Icmp ( mWorkspaces[i]->GetFilename(), filename ) )
1188                 {
1189                         SendMessage ( mMDIClient, WM_MDIACTIVATE, (WPARAM)mWorkspaces[i]->GetWindow ( ), 0 );
1190                         return false;
1191                 }
1192         }
1193
1194         SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_WAIT ) ) );
1195
1196         // Setup the default error.
1197         error = va("Failed to parse '%s'", filename );
1198
1199         rvGEWorkspace* workspace = new rvGEWorkspace ( this );
1200         if ( workspace->LoadFile ( filename, &error ) )
1201         {
1202                 HWND child;
1203                         
1204                 child = CreateMDIWindow("QUAKE4_GUIEDITOR_CHILD_CLASS",
1205                                                                 "Unamed.gui",
1206                                                                 WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN|WS_HSCROLL|WS_VSCROLL|WS_MAXIMIZE,
1207                                                                 CW_USEDEFAULT,
1208                                                                 CW_USEDEFAULT,
1209                                                                 640,
1210                                                                 480,
1211                                                                 mMDIClient,
1212                                                                 mInstance,
1213                                                                 (LONG)workspace );
1214                                                                                                                 
1215                 ShowWindow ( child, SW_SHOW );
1216                 
1217                 mOptions.AddRecentFile ( filename ); 
1218                 UpdateRecentFiles ( );
1219
1220                 result = true;
1221         }
1222         else
1223         {
1224                 MessageBox ( error, MB_OK|MB_ICONERROR );
1225         }
1226
1227         SetCursor ( LoadCursor ( NULL, MAKEINTRESOURCE(IDC_ARROW ) ) );
1228         
1229         return result;;
1230 }
1231
1232 /*
1233 ================
1234 rvGEApp::InitRecentFiles
1235
1236 Finds the file menu and the location within it where the MRU should
1237 be added.
1238 ================
1239 */
1240 bool rvGEApp::InitRecentFiles ( void )
1241 {
1242         int     i;
1243         int count;
1244
1245         mRecentFileMenu = GetSubMenu ( GetMenu(mMDIFrame), 0 );
1246         count                   = GetMenuItemCount ( mRecentFileMenu );
1247         
1248         for ( i = 0; i < count; i ++ )
1249         {
1250                 if ( GetMenuItemID ( mRecentFileMenu, i ) == ID_GUIED_FILE_MRU )
1251                 {
1252                         mRecentFileInsertPos = i;
1253                         DeleteMenu ( mRecentFileMenu, mRecentFileInsertPos, MF_BYPOSITION );
1254                         return true;
1255                 }
1256         }
1257         
1258         return false;
1259 }
1260
1261 /*
1262 ================
1263 rvGEApp::UpdateRecentFiles
1264
1265 Updates the mru in the menu
1266 ================
1267 */
1268 void rvGEApp::UpdateRecentFiles ( void )
1269 {
1270         int i;
1271         int j;
1272
1273         // Make sure everything is initialized
1274         if ( !mRecentFileMenu ) 
1275         {       
1276                 InitRecentFiles ( );
1277         }
1278
1279         // Delete all the old recent files from the menu's
1280         for ( i = 0; i < rvGEOptions::MAX_MRU_SIZE; i ++ )
1281         {
1282                 DeleteMenu ( mRecentFileMenu, ID_GUIED_FILE_MRU1 + i, MF_BYCOMMAND );
1283         }       
1284
1285         // Make sure there is a separator after the recent files
1286         if ( mOptions.GetRecentFileCount() )
1287         {
1288                 MENUITEMINFO info;
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 ) )
1294                 {
1295                         InsertMenu ( mRecentFileMenu, mRecentFileInsertPos, MF_BYPOSITION|MF_SEPARATOR|MF_ENABLED, 0, NULL );
1296                 }
1297         }
1298
1299         // Add the recent files to the menu now
1300         for ( j = 0, i = mOptions.GetRecentFileCount ( ) - 1; i >= 0; i --, j++ )
1301         {
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 );
1306         }               
1307 }
1308
1309 /*
1310 ================
1311 rvGEApp::CloseViewer
1312
1313 Closes the gui viewer
1314 ================
1315 */
1316 void rvGEApp::CloseViewer ( void )
1317 {
1318         if ( !mViewer )
1319         {
1320                 return;
1321         }
1322         
1323         mViewer->Destroy ( );
1324         delete mViewer;
1325         mViewer = NULL;
1326 }
1327
1328 /*
1329 ================
1330 rvGEApp::ToolWindowActivate
1331
1332 Handles the nc activate message for all tool windows
1333 ================
1334 */
1335 int     rvGEApp::ToolWindowActivate ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
1336 {
1337         bool    keepActive;
1338         bool    syncOthers;
1339         int             i;
1340         
1341         keepActive = ( wParam != 0 );
1342         syncOthers = true;
1343         
1344         for ( i = 0; i < mToolWindows.Num (); i ++ )
1345         {
1346                 if ( (HWND)lParam == mToolWindows[i] ) 
1347                 {
1348                         keepActive = true;
1349                         syncOthers = false;
1350                         break;
1351                 }
1352         }
1353         
1354         if ( lParam == -1 )
1355         {
1356                 return DefWindowProc ( hwnd, WM_NCACTIVATE, keepActive, 0 );
1357         }
1358
1359         if ( syncOthers )
1360         {
1361                 for ( i = 0; i < mToolWindows.Num(); i ++ )
1362                 {
1363                         if ( mToolWindows[i] != hwnd && mToolWindows[i] != (HWND) lParam )
1364                         {
1365                                 SendMessage ( mToolWindows[i], WM_NCACTIVATE, keepActive, (LONG)-1 );
1366                         }
1367                 }
1368         }
1369         
1370         return DefWindowProc ( hwnd, WM_NCACTIVATE, keepActive, lParam );
1371 }
1372
1373 /*
1374 ================
1375 rvGEApp::MessageBox
1376
1377 Displays a modal message box 
1378 ================
1379 */
1380 int rvGEApp::MessageBox ( const char* text, int flags )
1381 {
1382         return ::MessageBox ( mMDIFrame, text, "Quake 4 GUI Editor", flags );
1383 }
1384