2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Fred2/MainFrm.cpp $
15 * MainFrm.cpp : implementation of the CMainFrame class
16 * The main frame class of a document/view architechure, which we hate but must
17 * deal with, due to Microsoft limiting our freedom and forcing us to use whether
18 * we want to or not. The main frame is basically the container window that other
19 * view windows are within. In Fred, our view window is always maximized inside
20 * the main frame window, so you can't tell the difference between the two. A few
21 * old MFC events are handled here because the people working on the code before
22 * me (Hoffoss) decided to put it here. I've been putting it all in FredView.
25 * Revision 1.2 2002/06/09 04:41:16 relnev
26 * added copyright header
28 * Revision 1.1.1.1 2002/05/03 03:28:08 root
32 * 8 10/13/99 2:55p Jefff
33 * fixed unnumbered XSTRs
35 * 7 10/13/99 9:22a Daveb
36 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
37 * related to movies. Fixed launcher spawning from PXO screen.
39 * 6 9/14/99 11:07p Andsager
40 * Improve freddoc error message. Fix Frerd2 about box for "2" part of
43 * 5 9/08/99 12:07a Andsager
44 * Add browser based help to Fred
46 * 4 9/01/99 10:15a Dave
48 * 3 11/19/98 8:36a Dave
49 * Removed ST reordering of ships in Fred.
51 * 2 10/07/98 6:28p Dave
52 * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
53 * Fred. Globalized mission and campaign file extensions. Removed Silent
54 * Threat specific code.
56 * 1 10/07/98 3:02p Dave
58 * 1 10/07/98 3:00p Dave
60 * 31 9/16/98 6:54p Dave
61 * Upped max sexpression nodes to 1800 (from 1600). Changed FRED to sort
62 * the ship list box. Added code so that tracker stats are not stored with
65 * 30 3/09/98 10:56a Hoffoss
66 * Added jump node objects to Fred.
68 * 29 2/20/98 12:56p Adam
69 * Made ship class box even wider.
71 * 28 2/20/98 12:07p Hoffoss
72 * Made ship type combo box on toolbar wider.
74 * 27 9/30/97 2:11p Hoffoss
75 * Removed player start item from toolbar combo box.
77 * 26 8/21/97 5:39p Hoffoss
78 * Fixed warning when building optimized. Was MFC code I copied, which
79 * says something about MFC I guess.
81 * 25 8/17/97 10:22p Hoffoss
82 * Fixed several bugs in Fred with Undo feature. In the process, recoded
85 * 24 8/14/97 2:32p Hoffoss
86 * fixed bug where controlling an object doesn't cause screen updates, and
87 * added a number of cool features to viewpoint/control object code.
89 * 23 7/21/97 3:57p Hoffoss
90 * Removed group combo box from toolbar, since I don't think I'll ever get
93 * 22 6/26/97 12:39p Mike
94 * Add ship_type to ship_info and ships.tbl.
96 * 21 6/09/97 4:57p Hoffoss
97 * Added autosave and undo to Fred.
99 * 20 5/05/97 1:35p Hoffoss
100 * View window is now refocused when a new ship type selection is made.
102 * 19 5/01/97 10:54a Hoffoss
103 * Removed obsolete files/classes from Fred project, and any reference to
106 * 18 4/17/97 2:01p Hoffoss
107 * All dialog box window states are saved between sessions now.
109 * 17 4/03/97 11:35a Hoffoss
110 * Fixed bugs: viewpoint didn't reset, initial orders not updated when
111 * referenced ship is renamed or deleted.
113 * 16 3/10/97 4:58p Hoffoss
114 * Added waypoint and start types to drop down toolbar combo box and fixed
115 * context menu new ship type selection to also work.
117 * 15 3/10/97 12:54p Hoffoss
118 * Added drop down combo box to toolbar and fixed compiling errors Mark
119 * (maybe Mike?) introduced to code.
121 * 14 2/28/97 11:31a Hoffoss
122 * Implemented modeless dialog saving and restoring, and changed some
125 * 13 2/27/97 5:54p Hoffoss
126 * Implemented support for saving and restoring window positions.
128 * 12 2/17/97 5:28p Hoffoss
129 * Checked RCS headers, added them were missing, changing description to
130 * something better, etc where needed.
141 #include "fredview.h"
143 #include "messageeditordlg.h"
144 #include "shipclasseditordlg.h"
145 #include "missionnotesdlg.h"
150 #define new DEBUG_NEW
152 static char THIS_FILE[] = __FILE__;
155 /////////////////////////////////////////////////////////////////////////////
158 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
160 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
161 ON_MESSAGE(WM_MENU_POPUP_EDIT, OnMenuPopupTest)
162 ON_CBN_SELCHANGE(ID_NEW_SHIP_TYPE, OnNewShipTypeChange)
164 //{{AFX_MSG_MAP(CMainFrame)
166 ON_COMMAND(ID_EDITORS_AI_CLASSES, OnEditorsAiClasses)
167 ON_COMMAND(ID_EDITORS_GOALS, OnEditorsGoals)
168 ON_COMMAND(ID_EDITORS_ART, OnEditorsArt)
169 ON_COMMAND(ID_EDITORS_MUSIC, OnEditorsMusic)
170 ON_COMMAND(ID_EDITORS_SHIP_CLASSES, OnEditorsShipClasses)
171 ON_COMMAND(ID_EDITORS_SOUND, OnEditorsSound)
172 ON_COMMAND(ID_EDITORS_TERRAIN, OnEditorsTerrain)
173 ON_COMMAND(ID_FILE_MISSIONNOTES, OnFileMissionnotes)
176 ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
177 ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateViewStatusBar)
178 ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft)
179 ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight)
180 ON_COMMAND(ID_MIKE_GRIDCONTROL, OnMikeGridcontrol)
181 ON_COMMAND(IDR_MENU_POPUP_TOGGLE1, OnMenuPopupToggle1)
182 ON_UPDATE_COMMAND_UI(IDR_MENU_POPUP_TOGGLE1, OnUpdateMenuPopupToggle1)
184 ON_COMMAND(ID_HELP_INPUT_INTERFACE, OnHelpInputInterface)
187 ON_COMMAND(ID_HELP_FINDER, OnFredHelp)
188 ON_COMMAND(ID_HELP, OnFredHelp)
189 //ON_COMMAND(ID_CONTEXT_HELP, OnFredHelp)
190 //ON_COMMAND(ID_DEFAULT_HELP, OnFredHelp)
192 // Global help commands
195 #define FRED_HELP_URL "\\data\\freddocs\\index.html"
197 static UINT indicators[] =
199 ID_SEPARATOR, // status line indicator
202 ID_INDICATOR_MODIFIED,
204 // ID_INDICATOR_LEFT,
205 // ID_INDICATOR_RIGHT,
206 // ID_INDICATOR_CAPS,
208 // ID_INDICATOR_SCRL,
211 CMainFrame *Fred_main_wnd;
212 color_combo_box m_new_ship_type_combo_box;
214 /////////////////////////////////////////////////////////////////////////////
215 // CMainFrame construction/destruction
217 CMainFrame::CMainFrame()
221 CMainFrame::~CMainFrame()
225 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
230 if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
233 if (!m_wndToolBar.Create(this) ||
234 !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
236 TRACE0("Failed to create toolbar\n");
237 return -1; // fail to create
240 // Create the combo box
241 z = m_wndToolBar.CommandToIndex(ID_NEW_SHIP_TYPE);
243 m_wndToolBar.SetButtonInfo(z, ID_NEW_SHIP_TYPE, TBBS_SEPARATOR, 230);
245 // Design guide advises 12 pixel gap between combos and buttons
246 // m_wndToolBar.SetButtonInfo(1, ID_SEPARATOR, TBBS_SEPARATOR, 12);
247 m_wndToolBar.GetItemRect(z, &rect);
249 rect.bottom = rect.top + 550;
250 if (!m_new_ship_type_combo_box.Create(CBS_DROPDOWNLIST | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | LBS_OWNERDRAWFIXED,
251 rect, &m_wndToolBar, ID_NEW_SHIP_TYPE))
253 TRACE0("Failed to create new ship type combo-box\n");
257 /* if (!m_wndStatusBar.Create(this) ||
258 !m_wndStatusBar.SetIndicators(indicators,
259 sizeof(indicators)/sizeof(UINT)))
261 TRACE0("Failed to create status bar\n");
262 return -1; // fail to create
266 /* if (!m_wndStatusBar.Create(this,
267 WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR) ||
268 !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))*/
270 if (!m_wndStatusBar.Create(this) ||
271 !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
273 TRACE0("Failed to create status bar\n");
277 m_wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH, 0);
278 m_wndStatusBar.SetPaneInfo(1, 0, SBPS_NORMAL, 80);
279 m_wndStatusBar.SetPaneInfo(2, 0, SBPS_NORMAL, 180);
280 // m_wndStatusBar.SetPaneInfo(3, 0, SBPS_NORMAL, 100);
281 m_wndStatusBar.SetPaneInfo(4, 0, SBPS_NORMAL, 130);
284 // TODO: Remove this if you don't want tool tips or a resizeable toolbar
285 m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
286 CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
288 // TODO: Delete these three lines if you don't want the toolbar to
290 m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
291 EnableDocking(CBRS_ALIGN_ANY);
292 DockControlBar(&m_wndToolBar);
294 Fred_main_wnd = this;
295 Ship_editor_dialog.Create();
296 Wing_editor_dialog.Create();
297 Waypoint_editor_dialog.Create();
299 LoadBarState("Tools state");
303 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
305 // TODO: Modify the Window class or styles here by modifying
306 // the CREATESTRUCT cs
308 return CFrameWnd::PreCreateWindow(cs);
311 /////////////////////////////////////////////////////////////////////////////
312 // CMainFrame diagnostics
315 void CMainFrame::AssertValid() const
317 CFrameWnd::AssertValid();
320 void CMainFrame::Dump(CDumpContext& dc) const
327 //void CMainFrame::OnEditorsShips()
329 // CShipEditorDlg dlg;
335 void CMainFrame::OnEditorsAiClasses()
339 void CMainFrame::OnEditorsGoals()
343 void CMainFrame::OnEditorsArt()
347 void CMainFrame::OnEditorsMusic()
351 void CMainFrame::OnEditorsShipClasses()
355 void CMainFrame::OnEditorsSound()
359 void CMainFrame::OnEditorsTerrain()
363 void CMainFrame::OnFileMissionnotes()
365 CMissionNotesDlg dlg;
370 // I have been unable to get this message event to occur.
371 void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point)
373 CFrameWnd::OnLButtonUp(nFlags, point);
376 // This event is invoked when you click on the black X in the upper right corner
377 // or when you do File/Exit.
378 void CMainFrame::OnDestroy()
380 Fred_main_wnd = NULL;
381 CFrameWnd::OnDestroy();
384 void CMainFrame::OnViewStatusBar()
386 m_wndStatusBar.ShowWindow((m_wndStatusBar.GetStyle() & WS_VISIBLE) == 0);
390 void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI)
392 pCmdUI->SetCheck((m_wndStatusBar.GetStyle() & WS_VISIBLE) != 0);
395 void CMainFrame::OnUpdateLeft(CCmdUI* pCmdUI)
397 pCmdUI->Enable(::GetKeyState(VK_LBUTTON) < 0);
400 void CMainFrame::OnUpdateRight(CCmdUI* pCmdUI)
402 pCmdUI->Enable(::GetKeyState(VK_RBUTTON) < 0);
405 void CMainFrame::OnMikeGridcontrol()
414 void CMainFrame::OnMenuPopupToggle1()
416 if (Toggle1_var == 0)
423 void CMainFrame::OnUpdateMenuPopupToggle1(CCmdUI* pCmdUI)
425 pCmdUI->SetCheck(Toggle1_var);
428 LONG CMainFrame::OnMenuPopupTest(UINT wParam, LONG lParam)
433 point = * ((CPoint*) lParam);
435 ClientToScreen(&point);
437 menu.LoadMenu(IDR_MENU1);
438 menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
443 CPoint Global_point2;
445 void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
447 Global_point2 = point;
449 PostMessage(WM_MENU_POPUP_TEST, nFlags, (int) &Global_point2);
450 CFrameWnd::OnRButtonDown(nFlags, point);
453 void CMainFrame::OnHelpInputInterface()
460 void CMainFrame::OnClose()
462 theApp.write_ini_file();
463 SaveBarState("Tools state");
464 CFrameWnd::OnClose();
467 void CMainFrame::init_tools()
469 static int count = 0;
471 //int highest_terran_index;
472 //char ship_name[256];
475 SDL_assert(count < 2);
479 for (i=0; i<Num_ship_types; i++){
480 // don't add the pirate ship
481 if(Ship_info[i].flags & SIF_NO_FRED){
482 m_new_ship_type_combo_box.AddString("");
486 m_new_ship_type_combo_box.AddString(Ship_info[i].name);
489 // m_new_ship_type_combo_box.AddString("Player Start");
490 m_new_ship_type_combo_box.AddString("Jump Node");
491 m_new_ship_type_combo_box.AddString("Waypoint");
494 // now we want to sort special ships (mission disk) ----------------------
495 highest_terran_index = 0;
496 memset(ship_name, 0, 256);
497 while(m_new_ship_type_combo_box.GetLBText(highest_terran_index, ship_name) != CB_ERR){
498 ship_index = ship_info_lookup(ship_name);
499 if((ship_index < 0) || (ship_index >= Num_ship_types) || (Ship_info[ship_index].species != SPECIES_TERRAN)){
502 highest_terran_index++;
508 void CMainFrame::OnNewShipTypeChange()
511 Fred_view_wnd->SetFocus();
514 void color_combo_box::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
516 int m_cyText = 24, z;
520 // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
521 ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) ==
522 (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS));
524 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
526 // I think we need to do a lookup by ship name here
527 if(lpDrawItemStruct->itemID >= (uint)Num_ship_types){
528 z = lpDrawItemStruct->itemID;
530 memset(ship_name, 0, 256);
531 GetLBText(lpDrawItemStruct->itemID, ship_name);
532 z = ship_info_lookup(ship_name);
535 if ((z >= 0) && (lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
537 int cyItem = GetItemHeight(z);
538 BOOL fDisabled = !IsWindowEnabled();
540 COLORREF newTextColor = RGB(0x80, 0x80, 0x80); // light gray
542 if (z >= Num_ship_types)
543 newTextColor = RGB(0, 0, 0);
545 switch (Ship_info[z].species) {
546 case SPECIES_TERRAN: newTextColor = RGB(0, 0, 192); break;
547 case SPECIES_VASUDAN: newTextColor = RGB(0, 128, 0); break;
548 case SPECIES_SHIVAN: newTextColor = RGB(192, 0, 0); break;
549 case SPECIES_NONE: newTextColor = RGB(224, 128, 0); break;
553 COLORREF oldTextColor = pDC->SetTextColor(newTextColor);
554 COLORREF newBkColor = GetSysColor(COLOR_WINDOW);
555 COLORREF oldBkColor = pDC->SetBkColor(newBkColor);
557 if (newTextColor == newBkColor)
558 newTextColor = RGB(0xC0, 0xC0, 0xC0); // dark gray
560 if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0))
562 pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
563 pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
567 VERIFY(cyItem >= CalcMinimumItemHeight());
569 if (z == Id_select_type_jump_node)
570 strText = _T("Jump Node");
571 else if (z == Id_select_type_start)
572 strText = _T("Player Start");
573 else if (z == Id_select_type_waypoint)
574 strText = _T("Waypoint");
576 strText = _T(Ship_info[z].name);
577 // GetLBText(lpDrawItemStruct->itemID, strText);
579 pDC->ExtTextOut(lpDrawItemStruct->rcItem.left,
580 lpDrawItemStruct->rcItem.top + max(0, (cyItem - m_cyText) / 2),
581 ETO_OPAQUE, &(lpDrawItemStruct->rcItem), strText, strText.GetLength(), NULL);
583 pDC->SetTextColor(oldTextColor);
584 pDC->SetBkColor(oldBkColor);
587 if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0)
588 pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem));
591 int color_combo_box::CalcMinimumItemHeight()
595 if ((GetStyle() & (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) ==
596 (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED))
599 CFont* pOldFont = dc.SelectObject(GetFont());
601 VERIFY (dc.GetTextMetrics ( &tm ));
602 dc.SelectObject(pOldFont);
604 nResult = tm.tmHeight;
610 void color_combo_box::MeasureItem(LPMEASUREITEMSTRUCT)
612 // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
613 ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) ==
614 (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS));
617 int color_combo_box::SetCurSelNEW(int model_index)
619 if((model_index < 0) || (model_index >= Num_ship_types)){
620 return SetCurSel(model_index);
623 // lookup the ship name
624 return FindString(0, Ship_info[model_index].name);
627 int color_combo_box::GetCurSelNEW()
632 char *hmmm = ship_name;
634 // see if we have a special item (>= Num_ship_types)
635 cur_sel = GetCurSel();
636 if(cur_sel >= Num_ship_types){
640 // otherwise lookup the ship by name
641 memset(ship_name, 0, 256);
642 if(GetLBText(cur_sel, hmmm) == CB_ERR){
645 ship_info = ship_info_lookup(ship_name);
646 if((ship_info < 0) || (ship_info >= Num_ship_types)){
652 void CMainFrame::OnInitMenu(CMenu* pMenu)
656 if (Undo_available && !FREDDoc_ptr->undo_desc[1].IsEmpty())
657 str = "Undo " + FREDDoc_ptr->undo_desc[1] + "\tCtrl+Z";
659 str = "Undo\tCtrl+Z";
661 if (pMenu->GetMenuState(ID_EDIT_UNDO, MF_BYCOMMAND) != -1)
662 pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND, ID_EDIT_UNDO, str);
664 CFrameWnd::OnInitMenu(pMenu);
668 void url_launch(char *url)
672 r = (int) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOW);
677 case 0: txt = XSTR("The operating system is out of memory or resources.", 1107); break;
678 case ERROR_BAD_FORMAT: txt = XSTR("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).", 1108); break;
679 case SE_ERR_ACCESSDENIED: txt = XSTR("The operating system denied access to the specified file. ", 1109); break;
680 case SE_ERR_ASSOCINCOMPLETE: txt = XSTR("The filename association is incomplete or invalid.\r\n(You need to have a default Internet browser installed)", 1110); break;
681 case SE_ERR_DDEBUSY: txt = XSTR("The DDE transaction could not be completed because other DDE transactions were being processed.", 1111); break;
682 case SE_ERR_DDEFAIL: txt = XSTR("The DDE transaction failed.", 1112); break;
683 case SE_ERR_DDETIMEOUT: txt = XSTR("The DDE transaction could not be completed because the request timed out.", 1113); break;
684 case SE_ERR_DLLNOTFOUND: txt = XSTR("The specified dynamic-link library was not found.", 1114); break;
685 case SE_ERR_OOM: txt = XSTR("There was not enough memory to complete the operation.", 1115); break;
686 case SE_ERR_SHARE: txt = XSTR("A sharing violation occurred.", 1116); break;
688 // No browser installed message
690 case ERROR_FILE_NOT_FOUND:
691 case ERROR_PATH_NOT_FOUND: txt = XSTR("\r\nUnable to locate Fred Help file: \\data\\freddocs\\index.html\r\n", 1479); break;
693 default: txt = XSTR("Unknown error occurred.", 1118); break;
695 AfxMessageBox(txt, MB_OK | MB_ICONERROR);
700 void CMainFrame::OnFredHelp()
702 char buffer[_MAX_PATH];
705 strcpy(buffer, Fred_exe_dir);
708 char *last_slash = strrchr(buffer, '\\');
709 if ( last_slash == NULL) {
716 strcat(buffer, FRED_HELP_URL);