1 /**
2 * @file
3 * @brief Main Window for UFORadiant
4 * @note Creates the editing windows and dialogs, creates commands and
5 * registers preferences as well as handling internal paths
6 */
7
8 /*
9 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
10 For a list of contributors, see the accompanying CONTRIBUTORS file.
11
12 This file is part of GtkRadiant.
13
14 GtkRadiant is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
18
19 GtkRadiant is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with GtkRadiant; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "../../../../config.h"
31 #endif
32 #include "mainframe.h"
33 #include "radiant_i18n.h"
34
35 #include "debugging/debugging.h"
36 #include "version.h"
37
38 #include "ifilesystem.h"
39 #include "iundo.h"
40 #include "ifilter.h"
41 #include "iradiant.h"
42 #include "iregistry.h"
43 #include "igamemanager.h"
44 #include "iuimanager.h"
45 #include "itextures.h"
46 #include "igl.h"
47 #include "iump.h"
48 #include "ieventmanager.h"
49 #include "iselectionset.h"
50 #include "moduleobservers.h"
51
52 #include "os/path.h"
53 #include "os/file.h"
54
55 #include "gtkutil/clipboard.h"
56 #include "gtkutil/frame.h"
57 #include "gtkutil/glfont.h"
58 #include "gtkutil/glwidget.h"
59 #include "gtkutil/image.h"
60 #include "gtkutil/widget.h"
61 #include "gtkutil/IconTextMenuToggle.h"
62 #include "gtkutil/MultiMonitor.h"
63 #include "gtkutil/menu.h"
64
65 #include "SplitPaneLayout.h"
66 #include "../mru/MRU.h"
67 #include "../splash/Splash.h"
68 #include "../Icons.h"
69 #include "../common/ToolbarCreator.h"
70 #include "../menu/FiltersMenu.h"
71
72 #include "../../commands.h"
73 #include "../../map/AutoSaver.h"
74 #include "../../sidebar/sidebar.h"
75 #include "../../sidebar/texturebrowser.h"
76 #include "../../sidebar/surfaceinspector/surfaceinspector.h"
77 #include "../../settings/PreferenceDialog.h"
78 #include "../../render/OpenGLRenderSystem.h"
79 #include "../../camera/CamWnd.h"
80 #include "../../camera/GlobalCamera.h"
81 #include "../../xyview/GlobalXYWnd.h"
82 #include "../../textool/TexTool.h"
83 #include "../../server.h"
84 #include "../../plugin.h"
85 #include "../../windowobservers.h"
86 #include "../../environment.h"
87
88 namespace {
89 const std::string RKEY_WINDOW_STATE = "user/ui/mainFrame/window";
90 const std::string RKEY_MULTIMON_START_MONITOR = "user/ui/multiMonitor/startMonitorNum";
91 }
92
93 // Virtual file system
94 class VFSModuleObserver: public ModuleObserver
95 {
96 std::size_t m_unrealised;
97 public:
VFSModuleObserver()98 VFSModuleObserver () :
99 m_unrealised(1)
100 {
101 }
realise(void)102 void realise (void)
103 {
104 if (--m_unrealised == 0) {
105 GlobalFileSystem().initDirectory(GlobalRadiant().getFullGamePath());
106 GlobalFileSystem().initialise();
107 }
108 }
unrealise(void)109 void unrealise (void)
110 {
111 if (++m_unrealised == 1) {
112 GlobalFileSystem().shutdown();
113 }
114 }
115 };
116
117 namespace {
118 VFSModuleObserver g_VFSModuleObserver;
119 ModuleObservers g_gameModeObservers;
120 }
121
Radiant_attachGameModeObserver(ModuleObserver & observer)122 void Radiant_attachGameModeObserver (ModuleObserver& observer)
123 {
124 g_gameModeObservers.attach(observer);
125 }
126
Radiant_detachGameModeObserver(ModuleObserver & observer)127 void Radiant_detachGameModeObserver (ModuleObserver& observer)
128 {
129 g_gameModeObservers.detach(observer);
130 }
131
132 ModuleObservers g_gameToolsPathObservers;
133
Radiant_attachGameToolsPathObserver(ModuleObserver & observer)134 void Radiant_attachGameToolsPathObserver (ModuleObserver& observer)
135 {
136 g_gameToolsPathObservers.attach(observer);
137 }
138
Radiant_detachGameToolsPathObserver(ModuleObserver & observer)139 void Radiant_detachGameToolsPathObserver (ModuleObserver& observer)
140 {
141 g_gameToolsPathObservers.detach(observer);
142 }
143
144 // This is called from main() to start up the Radiant stuff.
Radiant_Initialise(void)145 void Radiant_Initialise (void)
146 {
147 // Load the ColourSchemes from the registry
148 ColourSchemes().loadColourSchemes();
149
150 // Load the other modules
151 Radiant_Construct(GlobalRadiantModuleServer());
152
153 g_VFSModuleObserver.realise();
154 GlobalTextureBrowser().createWidget();
155
156 // Rebuild the map path basing on the userGamePath
157 std::string newMapPath = GlobalRadiant().getFullGamePath() + "maps/";
158 g_mkdir_with_parents(newMapPath.c_str(), 0755);
159 Environment::Instance().setMapsPath(newMapPath);
160
161 g_gameToolsPathObservers.realise();
162 g_gameModeObservers.realise();
163
164 GlobalUMPSystem().init();
165
166 // Construct the MRU commands and menu structure
167 GlobalMRU().constructMenu();
168
169 // Initialise the most recently used files list
170 GlobalMRU().loadRecentFiles();
171
172 gtkutil::MultiMonitor::printMonitorInfo();
173 }
174
Radiant_Shutdown(void)175 void Radiant_Shutdown (void)
176 {
177 Environment::Instance().deletePathsFromRegistry();
178
179 GlobalMRU().saveRecentFiles();
180
181 g_VFSModuleObserver.unrealise();
182 Environment::Instance().setMapsPath("");
183 g_gameModeObservers.unrealise();
184 g_gameToolsPathObservers.unrealise();
185
186 Radiant_Destroy();
187 }
188
window_realize_remove_decoration(GtkWidget * widget,gpointer data)189 static gint window_realize_remove_decoration (GtkWidget* widget, gpointer data)
190 {
191 gdk_window_set_decorations(widget->window, (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MENU | GDK_DECOR_MINIMIZE
192 | GDK_DECOR_MAXIMIZE));
193 return FALSE;
194 }
195
196 class WaitDialog
197 {
198 public:
199 GtkWindow* m_window;
200 GtkLabel* m_label;
201 };
202
create_wait_dialog(const std::string & title,const std::string & text)203 static WaitDialog create_wait_dialog (const std::string& title, const std::string& text)
204 {
205 WaitDialog dialog;
206
207 dialog.m_window = create_floating_window(title, GlobalRadiant().getMainWindow());
208 gtk_window_set_resizable(dialog.m_window, FALSE);
209 gtk_container_set_border_width(GTK_CONTAINER(dialog.m_window), 0);
210 gtk_window_set_position(dialog.m_window, GTK_WIN_POS_CENTER_ON_PARENT);
211
212 g_signal_connect(G_OBJECT(dialog.m_window), "realize", G_CALLBACK(window_realize_remove_decoration), 0);
213
214 {
215 dialog.m_label = GTK_LABEL(gtk_label_new(text.c_str()));
216 gtk_misc_set_alignment(GTK_MISC(dialog.m_label), 0.5, 0.5);
217 gtk_label_set_justify(dialog.m_label, GTK_JUSTIFY_CENTER);
218 gtk_widget_show(GTK_WIDGET(dialog.m_label));
219 gtk_widget_set_size_request(GTK_WIDGET(dialog.m_label), 300, 100);
220
221 gtk_container_add(GTK_CONTAINER(dialog.m_window), GTK_WIDGET(dialog.m_label));
222 }
223 return dialog;
224 }
225
226 namespace {
227 clock_t g_lastRedrawTime = 0;
228 const clock_t c_redrawInterval = clock_t(CLOCKS_PER_SEC / 10);
229
redrawRequired(void)230 bool redrawRequired (void)
231 {
232 clock_t currentTime = std::clock();
233 if (currentTime - g_lastRedrawTime >= c_redrawInterval) {
234 g_lastRedrawTime = currentTime;
235 return true;
236 }
237 return false;
238 }
239 }
240
MainFrame_isActiveApp(void)241 static bool MainFrame_isActiveApp (void)
242 {
243 GList* list = gtk_window_list_toplevels();
244 for (GList* i = list; i != 0; i = g_list_next(i)) {
245 if (gtk_window_is_active(GTK_WINDOW(i->data))) {
246 return true;
247 }
248 }
249 return false;
250 }
251
252 typedef std::list<std::string> StringStack;
253 static StringStack g_wait_stack;
254 static WaitDialog g_wait;
255
ScreenUpdates_Enabled(void)256 bool ScreenUpdates_Enabled (void)
257 {
258 return g_wait_stack.empty();
259 }
260
ScreenUpdates_process(void)261 void ScreenUpdates_process (void)
262 {
263 if (redrawRequired() && GTK_WIDGET_VISIBLE(g_wait.m_window)) {
264 while (gtk_events_pending()) {
265 gtk_main_iteration();
266 }
267 }
268 }
269
ScreenUpdates_Disable(const std::string & message,const std::string & title)270 void ScreenUpdates_Disable (const std::string& message, const std::string& title)
271 {
272 if (g_wait_stack.empty()) {
273 map::AutoSaver().stopTimer();
274
275 while (gtk_events_pending()) {
276 gtk_main_iteration();
277 }
278
279 const bool isActiveApp = MainFrame_isActiveApp();
280
281 g_wait = create_wait_dialog(title, message);
282
283 if (isActiveApp) {
284 gtk_widget_show(GTK_WIDGET(g_wait.m_window));
285 gtk_grab_add(GTK_WIDGET(g_wait.m_window));
286 ScreenUpdates_process();
287 }
288 } else if (GTK_WIDGET_VISIBLE(g_wait.m_window)) {
289 gtk_label_set_text(g_wait.m_label, message.c_str());
290 ScreenUpdates_process();
291 }
292 g_wait_stack.push_back(message);
293 }
294
ScreenUpdates_Enable(void)295 void ScreenUpdates_Enable (void)
296 {
297 ASSERT_MESSAGE(!ScreenUpdates_Enabled(), "screen updates already enabled");
298 g_wait_stack.pop_back();
299 if (g_wait_stack.empty()) {
300 map::AutoSaver().startTimer();
301 gtk_grab_remove(GTK_WIDGET(g_wait.m_window));
302 destroy_floating_window(g_wait.m_window);
303 g_wait.m_window = 0;
304 } else if (GTK_WIDGET_VISIBLE(g_wait.m_window)) {
305 gtk_label_set_text(g_wait.m_label, g_wait_stack.back().c_str());
306 ScreenUpdates_process();
307 }
308 }
309
GlobalCamera_UpdateWindow(void)310 void GlobalCamera_UpdateWindow (void)
311 {
312 if (g_pParentWnd != 0) {
313 g_pParentWnd->GetCamWnd()->update();
314 }
315 }
316
XY_UpdateAllWindows(void)317 void XY_UpdateAllWindows (void)
318 {
319 if (g_pParentWnd != 0) {
320 GlobalXYWnd().updateAllViews();
321 }
322 }
323
UpdateAllWindows(void)324 void UpdateAllWindows (void)
325 {
326 GlobalCamera_UpdateWindow();
327 XY_UpdateAllWindows();
328 }
329
ClipperChangeNotify(void)330 void ClipperChangeNotify (void)
331 {
332 GlobalCamera_UpdateWindow();
333 XY_UpdateAllWindows();
334 }
335
create_main_statusbar(GtkWidget * pStatusLabel[c_count_status])336 static GtkWidget* create_main_statusbar (GtkWidget *pStatusLabel[c_count_status])
337 {
338 GtkTable* table = GTK_TABLE(gtk_table_new(1, c_count_status + 1, FALSE));
339 gtk_widget_show(GTK_WIDGET(table));
340
341 {
342 GtkLabel* label = GTK_LABEL(gtk_label_new(_("Label")));
343 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
344 gtk_misc_set_padding(GTK_MISC(label), 2, 2);
345 gtk_widget_show(GTK_WIDGET(label));
346 gtk_table_attach_defaults(table, GTK_WIDGET(label), 0, 1, 0, 1);
347 pStatusLabel[c_command_status] = GTK_WIDGET(label);
348 }
349
350 for (int i = 1; i < c_count_status; ++i) {
351 GtkFrame* frame = GTK_FRAME(gtk_frame_new(0));
352 gtk_widget_show(GTK_WIDGET(frame));
353 gtk_table_attach_defaults(table, GTK_WIDGET(frame), i, i + 1, 0, 1);
354 gtk_frame_set_shadow_type(frame, GTK_SHADOW_IN);
355
356 GtkLabel* label = GTK_LABEL(gtk_label_new(_("Label")));
357 gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
358 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
359 gtk_misc_set_padding(GTK_MISC(label), 2, 2);
360 gtk_widget_show(GTK_WIDGET(label));
361 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(label));
362 pStatusLabel[i] = GTK_WIDGET(label);
363 }
364
365 return GTK_WIDGET(table);
366 }
367
368 class MainWindowActive
369 {
notify(GtkWindow * window,gpointer dummy,MainWindowActive * self)370 static gboolean notify (GtkWindow* window, gpointer dummy, MainWindowActive* self)
371 {
372 if (g_wait.m_window != 0 && gtk_window_is_active(window) && !GTK_WIDGET_VISIBLE(g_wait.m_window)) {
373 gtk_widget_show(GTK_WIDGET(g_wait.m_window));
374 }
375
376 return FALSE;
377 }
378 public:
connect(GtkWindow * toplevel_window)379 void connect (GtkWindow* toplevel_window)
380 {
381 g_signal_connect(G_OBJECT(toplevel_window), "notify::is-active", G_CALLBACK(notify), this);
382 }
383 };
384
385 MainWindowActive g_MainWindowActive;
386
387 // =============================================================================
388 // MainFrame class
389
390 MainFrame* g_pParentWnd = 0;
391
MainFrame_getWindow(void)392 GtkWindow* MainFrame_getWindow (void)
393 {
394 if (g_pParentWnd == 0) {
395 return 0;
396 }
397 return g_pParentWnd->m_window;
398 }
399
MainFrame()400 MainFrame::MainFrame () :
401 m_window(0), g_currentToolMode(0), g_defaultToolMode(0), m_idleRedrawStatusText(RedrawStatusTextCaller(*this))
402 {
403 m_pCamWnd = 0;
404
405 for (int n = 0; n < c_count_status; n++) {
406 m_pStatusLabel[n] = 0;
407 }
408
409 // Register this class in the preference system so that the constructPreferencePage() gets called.
410 GlobalPreferenceSystem().addConstructor(this);
411
412 Create();
413 }
414
~MainFrame(void)415 MainFrame::~MainFrame (void)
416 {
417 SaveWindowInfo();
418
419 gtk_widget_hide(GTK_WIDGET(m_window));
420
421 Shutdown();
422
423 gtk_widget_destroy(GTK_WIDGET(m_window));
424 }
425
mainframe_delete(GtkWidget * widget,GdkEvent * event,gpointer data)426 static gint mainframe_delete (GtkWidget *widget, GdkEvent *event, gpointer data)
427 {
428 if (GlobalMap().askForSave("Exit Radiant")) {
429 gtk_main_quit();
430 }
431
432 return TRUE;
433 }
434
constructPreferencePage(PreferenceGroup & group)435 void MainFrame::constructPreferencePage (PreferenceGroup& group)
436 {
437 // Add another page for Multi-Monitor stuff
438 PreferencesPage* page(group.createPage(_("Display"), _("Multi Monitor")));
439
440 // Initialise the registry, if no key is set
441 if (GlobalRegistry().get(RKEY_MULTIMON_START_MONITOR).empty()) {
442 GlobalRegistry().set(RKEY_MULTIMON_START_MONITOR, "0");
443 }
444
445 ComboBoxValueList list;
446
447 for (int i = 0; i < gtkutil::MultiMonitor::getNumMonitors(); ++i) {
448 GdkRectangle rect = gtkutil::MultiMonitor::getMonitor(i);
449
450 list.push_back(string::format("Monitor %d (%dx%d)", i, rect.width, rect.height));
451 }
452
453 page->appendCombo(_("Start UFORadiant on monitor"), RKEY_MULTIMON_START_MONITOR, list);
454 }
455
456 /**
457 * @brief Create the user settable window layout
458 */
Create(void)459 void MainFrame::Create (void)
460 {
461 GtkWindow* window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
462
463 // do this here, because the commands are needed
464 _sidebar = new ui::Sidebar();
465 GtkWidget *sidebar = _sidebar->getWidget();
466
467 // Tell the XYManager which window the xyviews should be transient for
468 GlobalXYWnd().setGlobalParentWindow(window);
469
470 GlobalWindowObservers_connectTopLevel(window);
471
472 gtk_window_set_transient_for(ui::Splash::Instance().getWindow(), window);
473
474 #ifndef _WIN32
475 {
476 GdkPixbuf* pixbuf = gtkutil::getLocalPixbuf(ui::icons::ICON);
477 if (pixbuf != 0) {
478 gtk_window_set_icon(window, pixbuf);
479 g_object_unref(pixbuf);
480 }
481 }
482 #endif
483
484 gtk_widget_add_events(GTK_WIDGET(window), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK);
485 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(mainframe_delete), this);
486
487 m_position_tracker.connect(window);
488
489 g_MainWindowActive.connect(window);
490
491 GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
492 gtk_container_add(GTK_CONTAINER(window), vbox);
493 gtk_widget_show(vbox);
494
495 GlobalEventManager().connect(GTK_OBJECT(window));
496 GlobalEventManager().connectAccelGroup(GTK_WINDOW(window));
497
498 m_nCurrentStyle = eSplit;
499
500 // Create the Filter menu entries
501 ui::FiltersMenu::addItemsToMainMenu();
502
503 // Retrieve the "main" menubar from the UIManager
504 GtkMenuBar* mainMenu = GTK_MENU_BAR(GlobalUIManager().getMenuManager()->get("main"));
505 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(mainMenu), false, false, 0);
506
507 // Instantiate the ToolbarCreator and retrieve the standard toolbar widget
508 ui::ToolbarCreator toolbarCreator;
509
510 GtkToolbar* generalToolbar = toolbarCreator.getToolbar("view");
511 gtk_widget_show(GTK_WIDGET(generalToolbar));
512
513 GlobalSelectionSetManager().init(generalToolbar);
514
515 // Pack it into the main window
516 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(generalToolbar), FALSE, FALSE, 0);
517
518 GtkWidget* main_statusbar = create_main_statusbar(m_pStatusLabel);
519 gtk_box_pack_end(GTK_BOX(vbox), main_statusbar, FALSE, TRUE, 2);
520
521 GtkWidget* hbox = gtk_hbox_new(FALSE, 0);
522 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), TRUE, TRUE, 0);
523 gtk_widget_show(hbox);
524
525 GtkToolbar* main_toolbar_v = toolbarCreator.getToolbar("edit");
526 gtk_widget_show(GTK_WIDGET(main_toolbar_v));
527
528 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(main_toolbar_v), FALSE, FALSE, 0);
529
530
531 // Connect the window position tracker
532 _windowPosition.loadFromPath(RKEY_WINDOW_STATE);
533
534 // Yes, connect the position tracker, this overrides the existing setting.
535 _windowPosition.connect(window);
536
537 int startMonitor = GlobalRegistry().getInt(RKEY_MULTIMON_START_MONITOR);
538 if (startMonitor < gtkutil::MultiMonitor::getNumMonitors()) {
539 // Load the correct coordinates into the position tracker
540 _windowPosition.fitToScreen(gtkutil::MultiMonitor::getMonitor(startMonitor), 0.8f, 0.8f);
541 }
542
543 // Apply the position
544 _windowPosition.applyPosition();
545
546 int windowState = string::toInt(GlobalRegistry().getAttribute(RKEY_WINDOW_STATE, "state"), GDK_WINDOW_STATE_MAXIMIZED);
547 if (windowState & GDK_WINDOW_STATE_MAXIMIZED)
548 gtk_window_maximize(window);
549
550 m_window = window;
551
552 gtk_widget_show(GTK_WIDGET(window));
553
554 // The default XYView pointer
555 XYWnd* xyWnd;
556
557 GtkWidget* mainHBox = gtk_hbox_new(0, 0);
558 gtk_box_pack_start(GTK_BOX(hbox), mainHBox, TRUE, TRUE, 0);
559 gtk_widget_show(mainHBox);
560
561 int w, h;
562 gtk_window_get_size(window, &w, &h);
563
564 // camera
565 m_pCamWnd = GlobalCamera().newCamWnd();
566 GlobalCamera().setCamWnd(m_pCamWnd);
567 GlobalCamera().setParent(m_pCamWnd, window);
568 GtkWidget* camera = m_pCamWnd->getWidget();
569
570 // Allocate the three ortho views
571 xyWnd = GlobalXYWnd().createXY();
572 xyWnd->setViewType(XY);
573 GtkWidget* xy = xyWnd->getWidget();
574
575 XYWnd* yzWnd = GlobalXYWnd().createXY();
576 yzWnd->setViewType(YZ);
577 GtkWidget* yz = yzWnd->getWidget();
578
579 XYWnd* xzWnd = GlobalXYWnd().createXY();
580 xzWnd->setViewType(XZ);
581 GtkWidget* xz = xzWnd->getWidget();
582
583 // split view (4 views)
584 GtkHPaned* split = create_split_views(camera, yz, xy, xz);
585 gtk_box_pack_start(GTK_BOX(mainHBox), GTK_WIDGET(split), TRUE, TRUE, 0);
586
587 // greebo: In any layout, there is at least the XY view present, make it active
588 GlobalXYWnd().setActiveXY(xyWnd);
589
590 PreferencesDialog_constructWindow(window);
591
592 GlobalGrid().addGridChangeCallback(FreeCaller<XY_UpdateAllWindows> ());
593
594 /* enable button state tracker, set default states for begin */
595 GlobalUndoSystem().trackerAttach(m_saveStateTracker);
596
597 gtk_box_pack_start(GTK_BOX(mainHBox), GTK_WIDGET(sidebar), FALSE, FALSE, 0);
598
599 // Start the autosave timer so that it can periodically check the map for changes
600 map::AutoSaver().startTimer();
601 }
602
SaveWindowInfo(void)603 void MainFrame::SaveWindowInfo (void)
604 {
605 // Delete all the current window states from the registry
606 GlobalRegistry().deleteXPath(RKEY_WINDOW_STATE);
607
608 // Tell the position tracker to save the information
609 _windowPosition.saveToPath(RKEY_WINDOW_STATE);
610
611 GdkWindow* window = GTK_WIDGET(m_window)->window;
612 if (window != NULL)
613 GlobalRegistry().setAttribute(RKEY_WINDOW_STATE, "state", string::toString(gdk_window_get_state(window)));
614 }
615
Shutdown(void)616 void MainFrame::Shutdown (void)
617 {
618 map::AutoSaver().stopTimer();
619 ui::TexTool::Instance().shutdown();
620
621 GlobalUndoSystem().trackerDetach(m_saveStateTracker);
622
623 GlobalXYWnd().destroyViews();
624
625 GlobalCamera().deleteCamWnd(m_pCamWnd);
626 m_pCamWnd = 0;
627
628 PreferencesDialog_destroyWindow();
629
630 delete _sidebar;
631
632 // Stop the AutoSaver class from being called
633 map::AutoSaver().stopTimer();
634 }
635
636 /**
637 * @brief Updates the statusbar text with command, position, texture and so on
638 * @sa TextureBrowser_SetStatus
639 */
RedrawStatusText(void)640 void MainFrame::RedrawStatusText (void)
641 {
642 gtk_label_set_markup(GTK_LABEL(m_pStatusLabel[c_command_status]), m_command_status.c_str());
643 gtk_label_set_markup(GTK_LABEL(m_pStatusLabel[c_position_status]), m_position_status.c_str());
644 gtk_label_set_markup(GTK_LABEL(m_pStatusLabel[c_brushcount_status]), m_brushcount_status.c_str());
645 gtk_label_set_markup(GTK_LABEL(m_pStatusLabel[c_texture_status]), m_texture_status.c_str());
646 }
647
UpdateStatusText(void)648 void MainFrame::UpdateStatusText (void)
649 {
650 m_idleRedrawStatusText.queueDraw();
651 }
652
SetStatusText(std::string & status_text,const std::string & pText)653 void MainFrame::SetStatusText (std::string& status_text, const std::string& pText)
654 {
655 status_text = pText;
656 UpdateStatusText();
657 }
658
659 /**
660 * @brief Updates the first statusbar column
661 * @param[in] status the status to print into the first statusbar column
662 * @sa MainFrame::RedrawStatusText
663 * @sa MainFrame::SetStatusText
664 */
Sys_Status(const std::string & status)665 void Sys_Status (const std::string& status)
666 {
667 if (g_pParentWnd != 0) {
668 g_pParentWnd->SetStatusText(g_pParentWnd->m_command_status, status);
669 }
670 }
671
672 namespace {
673 GLFont g_font(0, 0);
674 }
675
GlobalGL_sharedContextCreated(void)676 static void GlobalGL_sharedContextCreated (void)
677 {
678 // report OpenGL information
679 globalOutputStream() << "GL_VENDOR: " << reinterpret_cast<const char*> (glGetString(GL_VENDOR)) << "\n";
680 globalOutputStream() << "GL_RENDERER: " << reinterpret_cast<const char*> (glGetString(GL_RENDERER)) << "\n";
681 globalOutputStream() << "GL_VERSION: " << reinterpret_cast<const char*> (glGetString(GL_VERSION)) << "\n";
682 globalOutputStream() << "GL_EXTENSIONS: " << reinterpret_cast<const char*> (glGetString(GL_EXTENSIONS)) << "\n";
683
684 QGL_sharedContextCreated(GlobalOpenGL());
685
686 GlobalShaderCache().realise();
687 GlobalTexturesCache().realise();
688
689 /* use default font here (Sans 10 is gtk default) */
690 GtkSettings *settings = gtk_settings_get_default();
691 gchar* fontname;
692 g_object_get(settings, "gtk-font-name", &fontname, (char*) 0);
693 g_font = glfont_create(fontname);
694 // Fallbacks
695 if (g_font.getPixelHeight() == -1)
696 g_font = glfont_create("Sans 10");
697 if (g_font.getPixelHeight() == -1)
698 g_font = glfont_create("fixed 10");
699 if (g_font.getPixelHeight() == -1)
700 g_font = glfont_create("courier new 10");
701
702 GlobalOpenGL().m_font = g_font.getDisplayList();
703 GlobalOpenGL().m_fontHeight = g_font.getPixelHeight();
704 }
705
GlobalGL_sharedContextDestroyed(void)706 static void GlobalGL_sharedContextDestroyed (void)
707 {
708 GlobalTexturesCache().unrealise();
709 GlobalShaderCache().unrealise();
710 }
711
712 #include "preferencesystem.h"
713 #include "stringio.h"
714
MainFrame_Construct(void)715 void MainFrame_Construct (void)
716 {
717 // Tell the FilterSystem to register its commands
718 GlobalFilterSystem().init();
719
720 Commands_Register();
721
722 GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated;
723 GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed;
724
725 // Broadcast the startup event
726 GlobalRadiant().broadcastStartupEvent();
727 }
728
MainFrame_Destroy(void)729 void MainFrame_Destroy (void)
730 {
731 // Broadcast shutdown event to RadiantListeners
732 GlobalRadiant().broadcastShutdownEvent();
733 }
734
735 /**
736 * Called whenever save was completed. This causes the UndoSaveTracker to mark this point as saved.
737 */
SaveComplete()738 void MainFrame::SaveComplete ()
739 {
740 m_saveStateTracker.storeState();
741 }
742