2 * $Logfile: /Freespace2/code/Fred2/MainFrm.cpp $
7 * MainFrm.cpp : implementation of the CMainFrame class
8 * The main frame class of a document/view architechure, which we hate but must
9 * deal with, due to Microsoft limiting our freedom and forcing us to use whether
10 * we want to or not. The main frame is basically the container window that other
11 * view windows are within. In Fred, our view window is always maximized inside
12 * the main frame window, so you can't tell the difference between the two. A few
13 * old MFC events are handled here because the people working on the code before
14 * me (Hoffoss) decided to put it here. I've been putting it all in FredView.
17 * Revision 1.1 2002/05/03 03:28:08 root
21 * 8 10/13/99 2:55p Jefff
22 * fixed unnumbered XSTRs
24 * 7 10/13/99 9:22a Daveb
25 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
26 * related to movies. Fixed launcher spawning from PXO screen.
28 * 6 9/14/99 11:07p Andsager
29 * Improve freddoc error message. Fix Frerd2 about box for "2" part of
32 * 5 9/08/99 12:07a Andsager
33 * Add browser based help to Fred
35 * 4 9/01/99 10:15a Dave
37 * 3 11/19/98 8:36a Dave
38 * Removed ST reordering of ships in Fred.
40 * 2 10/07/98 6:28p Dave
41 * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
42 * Fred. Globalized mission and campaign file extensions. Removed Silent
43 * Threat specific code.
45 * 1 10/07/98 3:02p Dave
47 * 1 10/07/98 3:00p Dave
49 * 31 9/16/98 6:54p Dave
50 * Upped max sexpression nodes to 1800 (from 1600). Changed FRED to sort
51 * the ship list box. Added code so that tracker stats are not stored with
54 * 30 3/09/98 10:56a Hoffoss
55 * Added jump node objects to Fred.
57 * 29 2/20/98 12:56p Adam
58 * Made ship class box even wider.
60 * 28 2/20/98 12:07p Hoffoss
61 * Made ship type combo box on toolbar wider.
63 * 27 9/30/97 2:11p Hoffoss
64 * Removed player start item from toolbar combo box.
66 * 26 8/21/97 5:39p Hoffoss
67 * Fixed warning when building optimized. Was MFC code I copied, which
68 * says something about MFC I guess.
70 * 25 8/17/97 10:22p Hoffoss
71 * Fixed several bugs in Fred with Undo feature. In the process, recoded
74 * 24 8/14/97 2:32p Hoffoss
75 * fixed bug where controlling an object doesn't cause screen updates, and
76 * added a number of cool features to viewpoint/control object code.
78 * 23 7/21/97 3:57p Hoffoss
79 * Removed group combo box from toolbar, since I don't think I'll ever get
82 * 22 6/26/97 12:39p Mike
83 * Add ship_type to ship_info and ships.tbl.
85 * 21 6/09/97 4:57p Hoffoss
86 * Added autosave and undo to Fred.
88 * 20 5/05/97 1:35p Hoffoss
89 * View window is now refocused when a new ship type selection is made.
91 * 19 5/01/97 10:54a Hoffoss
92 * Removed obsolete files/classes from Fred project, and any reference to
95 * 18 4/17/97 2:01p Hoffoss
96 * All dialog box window states are saved between sessions now.
98 * 17 4/03/97 11:35a Hoffoss
99 * Fixed bugs: viewpoint didn't reset, initial orders not updated when
100 * referenced ship is renamed or deleted.
102 * 16 3/10/97 4:58p Hoffoss
103 * Added waypoint and start types to drop down toolbar combo box and fixed
104 * context menu new ship type selection to also work.
106 * 15 3/10/97 12:54p Hoffoss
107 * Added drop down combo box to toolbar and fixed compiling errors Mark
108 * (maybe Mike?) introduced to code.
110 * 14 2/28/97 11:31a Hoffoss
111 * Implemented modeless dialog saving and restoring, and changed some
114 * 13 2/27/97 5:54p Hoffoss
115 * Implemented support for saving and restoring window positions.
117 * 12 2/17/97 5:28p Hoffoss
118 * Checked RCS headers, added them were missing, changing description to
119 * something better, etc where needed.
130 #include "fredview.h"
132 #include "messageeditordlg.h"
133 #include "shipclasseditordlg.h"
134 #include "missionnotesdlg.h"
139 #define new DEBUG_NEW
141 static char THIS_FILE[] = __FILE__;
144 /////////////////////////////////////////////////////////////////////////////
147 IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
149 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
150 ON_MESSAGE(WM_MENU_POPUP_EDIT, OnMenuPopupTest)
151 ON_CBN_SELCHANGE(ID_NEW_SHIP_TYPE, OnNewShipTypeChange)
153 //{{AFX_MSG_MAP(CMainFrame)
155 ON_COMMAND(ID_EDITORS_AI_CLASSES, OnEditorsAiClasses)
156 ON_COMMAND(ID_EDITORS_GOALS, OnEditorsGoals)
157 ON_COMMAND(ID_EDITORS_ART, OnEditorsArt)
158 ON_COMMAND(ID_EDITORS_MUSIC, OnEditorsMusic)
159 ON_COMMAND(ID_EDITORS_SHIP_CLASSES, OnEditorsShipClasses)
160 ON_COMMAND(ID_EDITORS_SOUND, OnEditorsSound)
161 ON_COMMAND(ID_EDITORS_TERRAIN, OnEditorsTerrain)
162 ON_COMMAND(ID_FILE_MISSIONNOTES, OnFileMissionnotes)
165 ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
166 ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateViewStatusBar)
167 ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft)
168 ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight)
169 ON_COMMAND(ID_MIKE_GRIDCONTROL, OnMikeGridcontrol)
170 ON_COMMAND(IDR_MENU_POPUP_TOGGLE1, OnMenuPopupToggle1)
171 ON_UPDATE_COMMAND_UI(IDR_MENU_POPUP_TOGGLE1, OnUpdateMenuPopupToggle1)
173 ON_COMMAND(ID_HELP_INPUT_INTERFACE, OnHelpInputInterface)
176 ON_COMMAND(ID_HELP_FINDER, OnFredHelp)
177 ON_COMMAND(ID_HELP, OnFredHelp)
178 //ON_COMMAND(ID_CONTEXT_HELP, OnFredHelp)
179 //ON_COMMAND(ID_DEFAULT_HELP, OnFredHelp)
181 // Global help commands
184 #define FRED_HELP_URL "\\data\\freddocs\\index.html"
186 static UINT indicators[] =
188 ID_SEPARATOR, // status line indicator
191 ID_INDICATOR_MODIFIED,
193 // ID_INDICATOR_LEFT,
194 // ID_INDICATOR_RIGHT,
195 // ID_INDICATOR_CAPS,
197 // ID_INDICATOR_SCRL,
200 CMainFrame *Fred_main_wnd;
201 color_combo_box m_new_ship_type_combo_box;
203 /////////////////////////////////////////////////////////////////////////////
204 // CMainFrame construction/destruction
206 CMainFrame::CMainFrame()
210 CMainFrame::~CMainFrame()
214 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
219 if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
222 if (!m_wndToolBar.Create(this) ||
223 !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
225 TRACE0("Failed to create toolbar\n");
226 return -1; // fail to create
229 // Create the combo box
230 z = m_wndToolBar.CommandToIndex(ID_NEW_SHIP_TYPE);
232 m_wndToolBar.SetButtonInfo(z, ID_NEW_SHIP_TYPE, TBBS_SEPARATOR, 230);
234 // Design guide advises 12 pixel gap between combos and buttons
235 // m_wndToolBar.SetButtonInfo(1, ID_SEPARATOR, TBBS_SEPARATOR, 12);
236 m_wndToolBar.GetItemRect(z, &rect);
238 rect.bottom = rect.top + 550;
239 if (!m_new_ship_type_combo_box.Create(CBS_DROPDOWNLIST | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | LBS_OWNERDRAWFIXED,
240 rect, &m_wndToolBar, ID_NEW_SHIP_TYPE))
242 TRACE0("Failed to create new ship type combo-box\n");
246 /* if (!m_wndStatusBar.Create(this) ||
247 !m_wndStatusBar.SetIndicators(indicators,
248 sizeof(indicators)/sizeof(UINT)))
250 TRACE0("Failed to create status bar\n");
251 return -1; // fail to create
255 /* if (!m_wndStatusBar.Create(this,
256 WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR) ||
257 !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))*/
259 if (!m_wndStatusBar.Create(this) ||
260 !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
262 TRACE0("Failed to create status bar\n");
266 m_wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH, 0);
267 m_wndStatusBar.SetPaneInfo(1, 0, SBPS_NORMAL, 80);
268 m_wndStatusBar.SetPaneInfo(2, 0, SBPS_NORMAL, 180);
269 // m_wndStatusBar.SetPaneInfo(3, 0, SBPS_NORMAL, 100);
270 m_wndStatusBar.SetPaneInfo(4, 0, SBPS_NORMAL, 130);
273 // TODO: Remove this if you don't want tool tips or a resizeable toolbar
274 m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
275 CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
277 // TODO: Delete these three lines if you don't want the toolbar to
279 m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM);
280 EnableDocking(CBRS_ALIGN_ANY);
281 DockControlBar(&m_wndToolBar);
283 Fred_main_wnd = this;
284 Ship_editor_dialog.Create();
285 Wing_editor_dialog.Create();
286 Waypoint_editor_dialog.Create();
288 LoadBarState("Tools state");
292 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
294 // TODO: Modify the Window class or styles here by modifying
295 // the CREATESTRUCT cs
297 return CFrameWnd::PreCreateWindow(cs);
300 /////////////////////////////////////////////////////////////////////////////
301 // CMainFrame diagnostics
304 void CMainFrame::AssertValid() const
306 CFrameWnd::AssertValid();
309 void CMainFrame::Dump(CDumpContext& dc) const
316 //void CMainFrame::OnEditorsShips()
318 // CShipEditorDlg dlg;
324 void CMainFrame::OnEditorsAiClasses()
328 void CMainFrame::OnEditorsGoals()
332 void CMainFrame::OnEditorsArt()
336 void CMainFrame::OnEditorsMusic()
340 void CMainFrame::OnEditorsShipClasses()
344 void CMainFrame::OnEditorsSound()
348 void CMainFrame::OnEditorsTerrain()
352 void CMainFrame::OnFileMissionnotes()
354 CMissionNotesDlg dlg;
359 // I have been unable to get this message event to occur.
360 void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point)
362 CFrameWnd::OnLButtonUp(nFlags, point);
365 // This event is invoked when you click on the black X in the upper right corner
366 // or when you do File/Exit.
367 void CMainFrame::OnDestroy()
369 Fred_main_wnd = NULL;
370 CFrameWnd::OnDestroy();
373 void CMainFrame::OnViewStatusBar()
375 m_wndStatusBar.ShowWindow((m_wndStatusBar.GetStyle() & WS_VISIBLE) == 0);
379 void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI)
381 pCmdUI->SetCheck((m_wndStatusBar.GetStyle() & WS_VISIBLE) != 0);
384 void CMainFrame::OnUpdateLeft(CCmdUI* pCmdUI)
386 pCmdUI->Enable(::GetKeyState(VK_LBUTTON) < 0);
389 void CMainFrame::OnUpdateRight(CCmdUI* pCmdUI)
391 pCmdUI->Enable(::GetKeyState(VK_RBUTTON) < 0);
394 void CMainFrame::OnMikeGridcontrol()
403 void CMainFrame::OnMenuPopupToggle1()
405 if (Toggle1_var == 0)
412 void CMainFrame::OnUpdateMenuPopupToggle1(CCmdUI* pCmdUI)
414 pCmdUI->SetCheck(Toggle1_var);
417 LONG CMainFrame::OnMenuPopupTest(UINT wParam, LONG lParam)
422 point = * ((CPoint*) lParam);
424 ClientToScreen(&point);
426 menu.LoadMenu(IDR_MENU1);
427 menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
432 CPoint Global_point2;
434 void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
436 Global_point2 = point;
438 PostMessage(WM_MENU_POPUP_TEST, nFlags, (int) &Global_point2);
439 CFrameWnd::OnRButtonDown(nFlags, point);
442 void CMainFrame::OnHelpInputInterface()
449 void CMainFrame::OnClose()
451 theApp.write_ini_file();
452 SaveBarState("Tools state");
453 CFrameWnd::OnClose();
456 void CMainFrame::init_tools()
458 static int count = 0;
460 //int highest_terran_index;
461 //char ship_name[256];
468 for (i=0; i<Num_ship_types; i++){
469 // don't add the pirate ship
470 if(Ship_info[i].flags & SIF_NO_FRED){
471 m_new_ship_type_combo_box.AddString("");
475 m_new_ship_type_combo_box.AddString(Ship_info[i].name);
478 // m_new_ship_type_combo_box.AddString("Player Start");
479 m_new_ship_type_combo_box.AddString("Jump Node");
480 m_new_ship_type_combo_box.AddString("Waypoint");
483 // now we want to sort special ships (mission disk) ----------------------
484 highest_terran_index = 0;
485 memset(ship_name, 0, 256);
486 while(m_new_ship_type_combo_box.GetLBText(highest_terran_index, ship_name) != CB_ERR){
487 ship_index = ship_info_lookup(ship_name);
488 if((ship_index < 0) || (ship_index >= Num_ship_types) || (Ship_info[ship_index].species != SPECIES_TERRAN)){
491 highest_terran_index++;
497 void CMainFrame::OnNewShipTypeChange()
500 Fred_view_wnd->SetFocus();
503 void color_combo_box::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
505 int m_cyText = 24, z;
509 // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
510 ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) ==
511 (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS));
513 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
515 // I think we need to do a lookup by ship name here
516 if(lpDrawItemStruct->itemID >= (uint)Num_ship_types){
517 z = lpDrawItemStruct->itemID;
519 memset(ship_name, 0, 256);
520 GetLBText(lpDrawItemStruct->itemID, ship_name);
521 z = ship_info_lookup(ship_name);
524 if ((z >= 0) && (lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)))
526 int cyItem = GetItemHeight(z);
527 BOOL fDisabled = !IsWindowEnabled();
529 COLORREF newTextColor = RGB(0x80, 0x80, 0x80); // light gray
531 if (z >= Num_ship_types)
532 newTextColor = RGB(0, 0, 0);
534 switch (Ship_info[z].species) {
535 case SPECIES_TERRAN: newTextColor = RGB(0, 0, 192); break;
536 case SPECIES_VASUDAN: newTextColor = RGB(0, 128, 0); break;
537 case SPECIES_SHIVAN: newTextColor = RGB(192, 0, 0); break;
538 case SPECIES_NONE: newTextColor = RGB(224, 128, 0); break;
542 COLORREF oldTextColor = pDC->SetTextColor(newTextColor);
543 COLORREF newBkColor = GetSysColor(COLOR_WINDOW);
544 COLORREF oldBkColor = pDC->SetBkColor(newBkColor);
546 if (newTextColor == newBkColor)
547 newTextColor = RGB(0xC0, 0xC0, 0xC0); // dark gray
549 if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0))
551 pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT));
552 pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT));
556 VERIFY(cyItem >= CalcMinimumItemHeight());
558 if (z == Id_select_type_jump_node)
559 strText = _T("Jump Node");
560 else if (z == Id_select_type_start)
561 strText = _T("Player Start");
562 else if (z == Id_select_type_waypoint)
563 strText = _T("Waypoint");
565 strText = _T(Ship_info[z].name);
566 // GetLBText(lpDrawItemStruct->itemID, strText);
568 pDC->ExtTextOut(lpDrawItemStruct->rcItem.left,
569 lpDrawItemStruct->rcItem.top + max(0, (cyItem - m_cyText) / 2),
570 ETO_OPAQUE, &(lpDrawItemStruct->rcItem), strText, strText.GetLength(), NULL);
572 pDC->SetTextColor(oldTextColor);
573 pDC->SetBkColor(oldBkColor);
576 if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0)
577 pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem));
580 int color_combo_box::CalcMinimumItemHeight()
584 if ((GetStyle() & (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) ==
585 (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED))
588 CFont* pOldFont = dc.SelectObject(GetFont());
590 VERIFY (dc.GetTextMetrics ( &tm ));
591 dc.SelectObject(pOldFont);
593 nResult = tm.tmHeight;
599 void color_combo_box::MeasureItem(LPMEASUREITEMSTRUCT)
601 // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE
602 ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) ==
603 (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS));
606 int color_combo_box::SetCurSelNEW(int model_index)
608 if((model_index < 0) || (model_index >= Num_ship_types)){
609 return SetCurSel(model_index);
612 // lookup the ship name
613 return FindString(0, Ship_info[model_index].name);
616 int color_combo_box::GetCurSelNEW()
621 char *hmmm = ship_name;
623 // see if we have a special item (>= Num_ship_types)
624 cur_sel = GetCurSel();
625 if(cur_sel >= Num_ship_types){
629 // otherwise lookup the ship by name
630 memset(ship_name, 0, 256);
631 if(GetLBText(cur_sel, hmmm) == CB_ERR){
634 ship_info = ship_info_lookup(ship_name);
635 if((ship_info < 0) || (ship_info >= Num_ship_types)){
641 void CMainFrame::OnInitMenu(CMenu* pMenu)
645 if (Undo_available && !FREDDoc_ptr->undo_desc[1].IsEmpty())
646 str = "Undo " + FREDDoc_ptr->undo_desc[1] + "\tCtrl+Z";
648 str = "Undo\tCtrl+Z";
650 if (pMenu->GetMenuState(ID_EDIT_UNDO, MF_BYCOMMAND) != -1)
651 pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND, ID_EDIT_UNDO, str);
653 CFrameWnd::OnInitMenu(pMenu);
657 void url_launch(char *url)
661 r = (int) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOW);
666 case 0: txt = XSTR("The operating system is out of memory or resources.", 1107); break;
667 case ERROR_BAD_FORMAT: txt = XSTR("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).", 1108); break;
668 case SE_ERR_ACCESSDENIED: txt = XSTR("The operating system denied access to the specified file. ", 1109); break;
669 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;
670 case SE_ERR_DDEBUSY: txt = XSTR("The DDE transaction could not be completed because other DDE transactions were being processed.", 1111); break;
671 case SE_ERR_DDEFAIL: txt = XSTR("The DDE transaction failed.", 1112); break;
672 case SE_ERR_DDETIMEOUT: txt = XSTR("The DDE transaction could not be completed because the request timed out.", 1113); break;
673 case SE_ERR_DLLNOTFOUND: txt = XSTR("The specified dynamic-link library was not found.", 1114); break;
674 case SE_ERR_OOM: txt = XSTR("There was not enough memory to complete the operation.", 1115); break;
675 case SE_ERR_SHARE: txt = XSTR("A sharing violation occurred.", 1116); break;
677 // No browser installed message
679 case ERROR_FILE_NOT_FOUND:
680 case ERROR_PATH_NOT_FOUND: txt = XSTR("\r\nUnable to locate Fred Help file: \\data\\freddocs\\index.html\r\n", 1479); break;
682 default: txt = XSTR("Unknown error occurred.", 1118); break;
684 AfxMessageBox(txt, MB_OK | MB_ICONERROR);
689 void CMainFrame::OnFredHelp()
691 char buffer[_MAX_PATH];
694 strcpy(buffer, Fred_exe_dir);
697 char *last_slash = strrchr(buffer, '\\');
698 if ( last_slash == NULL) {
705 strcat(buffer, FRED_HELP_URL);