2 Copyright (c) 2001, Loki software, inc.
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 Redistributions of source code must retain the above copyright notice, this list
9 of conditions and the following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
15 Neither the name of Loki software nor the names of its contributors may be used
16 to endorse or promote products derived from this software without specific prior
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 // Some small dialogs that don't need much
34 // Leonardo Zide (leo@lokigames.com)
39 #include "debugging/debugging.h"
44 #include "iscenegraph.h"
45 #include "iselection.h"
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtkmain.h>
49 #include <gtk/gtkentry.h>
50 #include <gtk/gtkhbox.h>
51 #include <gtk/gtkvbox.h>
52 #include <gtk/gtkframe.h>
53 #include <gtk/gtklabel.h>
54 #include <gtk/gtktable.h>
55 #include <gtk/gtkbutton.h>
56 #include <gtk/gtkcombobox.h>
57 #include <gtk/gtkscrolledwindow.h>
58 #include <gtk/gtktextview.h>
59 #include <gtk/gtktextbuffer.h>
60 #include <gtk/gtktreeview.h>
61 #include <gtk/gtkcellrenderertext.h>
62 #include <gtk/gtktreeselection.h>
63 #include <gtk/gtkliststore.h>
66 #include "math/aabb.h"
67 #include "container/array.h"
68 #include "generic/static.h"
69 #include "stream/stringstream.h"
71 #include "gtkutil/messagebox.h"
72 #include "gtkutil/image.h"
75 #include "brushmanip.h"
78 #include "texwindow.h"
80 #include "mainframe.h"
81 #include "preferences.h"
87 // =============================================================================
88 // Project settings dialog
90 class GameComboConfiguration
93 const char* basegame_dir;
95 const char* known_dir;
99 GameComboConfiguration() :
100 basegame_dir(g_pGameDescription->getRequiredKeyValue("basegame")),
101 basegame(g_pGameDescription->getRequiredKeyValue("basegamename")),
102 known_dir(g_pGameDescription->getKeyValue("knowngame")),
103 known(g_pGameDescription->getKeyValue("knowngamename")),
104 custom(g_pGameDescription->getRequiredKeyValue("unknowngamename"))
109 typedef LazyStatic<GameComboConfiguration> LazyStaticGameComboConfiguration;
111 inline GameComboConfiguration& globalGameComboConfiguration()
113 return LazyStaticGameComboConfiguration::instance();
119 gamecombo_t(int _game, const char* _fs_game, bool _sensitive)
120 : game(_game), fs_game(_fs_game), sensitive(_sensitive)
127 gamecombo_t gamecombo_for_dir(const char* dir)
129 if(string_equal(dir, globalGameComboConfiguration().basegame_dir))
131 return gamecombo_t(0, "", false);
133 else if(string_equal(dir, globalGameComboConfiguration().known_dir))
135 return gamecombo_t(1, dir, false);
139 return gamecombo_t(string_empty(globalGameComboConfiguration().known_dir) ? 1 : 2, dir, true);
143 gamecombo_t gamecombo_for_gamename(const char* gamename)
145 if ((strlen(gamename) == 0) || !strcmp(gamename, globalGameComboConfiguration().basegame))
147 return gamecombo_t(0, "", false);
149 else if (!strcmp(gamename, globalGameComboConfiguration().known))
151 return gamecombo_t(1, globalGameComboConfiguration().known_dir, false);
155 return gamecombo_t(string_empty(globalGameComboConfiguration().known_dir) ? 1 : 2, "", true);
159 inline void path_copy_clean(char* destination, const char* source)
161 char* i = destination;
163 while(*source != '\0')
165 *i++ = (*source == '\\') ? '/' : *source;
169 if(i != destination && *(i-1) != '/')
178 GtkComboBox* game_select;
179 GtkEntry* fsgame_entry;
182 gboolean OnSelchangeComboWhatgame(GtkWidget *widget, GameCombo* combo)
184 const char *gamename;
187 gtk_combo_box_get_active_iter(combo->game_select, &iter);
188 gtk_tree_model_get(gtk_combo_box_get_model(combo->game_select), &iter, 0, (gpointer*)&gamename, -1);
191 gamecombo_t gamecombo = gamecombo_for_gamename(gamename);
193 gtk_entry_set_text(combo->fsgame_entry, gamecombo.fs_game);
194 gtk_widget_set_sensitive(GTK_WIDGET(combo->fsgame_entry), gamecombo.sensitive);
202 bool do_mapping_mode;
203 const char* sp_mapping_mode;
204 const char* mp_mapping_mode;
207 do_mapping_mode(!string_empty(g_pGameDescription->getKeyValue("show_gamemode"))),
208 sp_mapping_mode("Single Player mapping mode"),
209 mp_mapping_mode("Multiplayer mapping mode")
214 typedef LazyStatic<MappingMode> LazyStaticMappingMode;
216 inline MappingMode& globalMappingMode()
218 return LazyStaticMappingMode::instance();
221 class ProjectSettingsDialog
224 GameCombo game_combo;
225 GtkComboBox* gamemode_combo;
228 GtkWindow* ProjectSettingsDialog_construct(ProjectSettingsDialog& dialog, ModalDialog& modal)
230 GtkWindow* window = create_dialog_window(MainFrame_getWindow(), "Project Settings", G_CALLBACK(dialog_delete_callback), &modal);
233 GtkTable* table1 = create_dialog_table(1, 2, 4, 4, 4);
234 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(table1));
236 GtkVBox* vbox = create_dialog_vbox(4);
237 gtk_table_attach(table1, GTK_WIDGET(vbox), 1, 2, 0, 1,
238 (GtkAttachOptions) (GTK_FILL),
239 (GtkAttachOptions) (GTK_FILL), 0, 0);
241 GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &modal);
242 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
245 GtkButton* button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &modal);
246 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
250 GtkFrame* frame = create_dialog_frame("Project settings");
251 gtk_table_attach(table1, GTK_WIDGET(frame), 0, 1, 0, 1,
252 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
253 (GtkAttachOptions) (GTK_FILL), 0, 0);
255 GtkTable* table2 = create_dialog_table((globalMappingMode().do_mapping_mode) ? 4 : 3, 2, 4, 4, 4);
256 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(table2));
259 GtkLabel* label = GTK_LABEL(gtk_label_new("Select mod"));
260 gtk_widget_show(GTK_WIDGET(label));
261 gtk_table_attach(table2, GTK_WIDGET(label), 0, 1, 0, 1,
262 (GtkAttachOptions) (GTK_FILL),
263 (GtkAttachOptions) (0), 0, 0);
264 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
267 dialog.game_combo.game_select = GTK_COMBO_BOX(gtk_combo_box_new_text());
269 gtk_combo_box_append_text(dialog.game_combo.game_select, globalGameComboConfiguration().basegame);
270 if(globalGameComboConfiguration().known[0] != '\0')
271 gtk_combo_box_append_text(dialog.game_combo.game_select, globalGameComboConfiguration().known);
272 gtk_combo_box_append_text(dialog.game_combo.game_select, globalGameComboConfiguration().custom);
274 gtk_widget_show(GTK_WIDGET(dialog.game_combo.game_select));
275 gtk_table_attach(table2, GTK_WIDGET(dialog.game_combo.game_select), 1, 2, 0, 1,
276 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
277 (GtkAttachOptions) (0), 0, 0);
279 g_signal_connect(G_OBJECT(dialog.game_combo.game_select), "changed", G_CALLBACK(OnSelchangeComboWhatgame), &dialog.game_combo);
283 GtkLabel* label = GTK_LABEL(gtk_label_new("fs_game"));
284 gtk_widget_show(GTK_WIDGET(label));
285 gtk_table_attach(table2, GTK_WIDGET(label), 0, 1, 1, 2,
286 (GtkAttachOptions) (GTK_FILL),
287 (GtkAttachOptions) (0), 0, 0);
288 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
291 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
292 gtk_widget_show(GTK_WIDGET(entry));
293 gtk_table_attach(table2, GTK_WIDGET(entry), 1, 2, 1, 2,
294 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
295 (GtkAttachOptions) (0), 0, 0);
297 dialog.game_combo.fsgame_entry = entry;
300 if(globalMappingMode().do_mapping_mode)
302 GtkLabel* label = GTK_LABEL(gtk_label_new("Mapping mode"));
303 gtk_widget_show(GTK_WIDGET(label));
304 gtk_table_attach(table2, GTK_WIDGET(label), 0, 1, 3, 4,
305 (GtkAttachOptions) (GTK_FILL),
306 (GtkAttachOptions) (0), 0, 0);
307 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
309 GtkComboBox* combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
310 gtk_combo_box_append_text(combo, globalMappingMode().sp_mapping_mode);
311 gtk_combo_box_append_text(combo, globalMappingMode().mp_mapping_mode);
313 gtk_widget_show(GTK_WIDGET(combo));
314 gtk_table_attach(table2, GTK_WIDGET(combo), 1, 2, 3, 4,
315 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
316 (GtkAttachOptions) (0), 0, 0);
318 dialog.gamemode_combo = combo;
324 // initialise the fs_game selection from the project settings into the dialog
325 const char* dir = gamename_get();
326 gamecombo_t gamecombo = gamecombo_for_dir(dir);
328 gtk_combo_box_set_active(dialog.game_combo.game_select, gamecombo.game);
329 gtk_entry_set_text(dialog.game_combo.fsgame_entry, gamecombo.fs_game);
330 gtk_widget_set_sensitive(GTK_WIDGET(dialog.game_combo.fsgame_entry), gamecombo.sensitive);
332 if(globalMappingMode().do_mapping_mode)
334 const char *gamemode = gamemode_get();
335 if (string_empty(gamemode) || string_equal(gamemode, "sp"))
337 gtk_combo_box_set_active(dialog.gamemode_combo, 0);
341 gtk_combo_box_set_active(dialog.gamemode_combo, 1);
348 void ProjectSettingsDialog_ok(ProjectSettingsDialog& dialog)
350 const char* dir = gtk_entry_get_text(dialog.game_combo.fsgame_entry);
352 const char* new_gamename = path_equal(dir, globalGameComboConfiguration().basegame_dir)
356 if(!path_equal(new_gamename, gamename_get()))
358 ScopeDisableScreenUpdates disableScreenUpdates("Processing...", "Changing Game Name");
360 EnginePath_Unrealise();
362 gamename_set(new_gamename);
364 EnginePath_Realise();
367 if(globalMappingMode().do_mapping_mode)
369 // read from gamemode_combo
370 int active = gtk_combo_box_get_active(dialog.gamemode_combo);
371 if(active == -1 || active == 0)
382 void DoProjectSettings()
384 if(ConfirmModified("Edit Project Settings"))
387 ProjectSettingsDialog dialog;
389 GtkWindow* window = ProjectSettingsDialog_construct(dialog, modal);
391 if(modal_dialog_show(window, modal) == eIDOK)
393 ProjectSettingsDialog_ok(dialog);
396 gtk_widget_destroy(GTK_WIDGET(window));
400 // =============================================================================
401 // Arbitrary Sides dialog
403 void DoSides (int type, int axis)
406 GtkEntry* sides_entry;
408 GtkWindow* window = create_dialog_window(MainFrame_getWindow(), "Arbitrary sides", G_CALLBACK(dialog_delete_callback), &dialog);
410 GtkAccelGroup* accel = gtk_accel_group_new();
411 gtk_window_add_accel_group(window, accel);
414 GtkHBox* hbox = create_dialog_hbox(4, 4);
415 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
417 GtkLabel* label = GTK_LABEL(gtk_label_new("Sides:"));
418 gtk_widget_show(GTK_WIDGET(label));
419 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
422 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
423 gtk_widget_show(GTK_WIDGET(entry));
424 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), FALSE, FALSE, 0);
426 gtk_widget_grab_focus(GTK_WIDGET(entry));
429 GtkVBox* vbox = create_dialog_vbox(4);
430 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
432 GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog);
433 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
434 widget_make_default(GTK_WIDGET(button));
435 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
438 GtkButton* button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &dialog);
439 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
440 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
445 if(modal_dialog_show(window, dialog) == eIDOK)
447 const char *str = gtk_entry_get_text(sides_entry);
449 Scene_BrushConstructPrefab(GlobalSceneGraph(), (EBrushPrefab)type, atoi(str), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()));
452 gtk_widget_destroy(GTK_WIDGET(window));
455 // =============================================================================
456 // About dialog (no program is complete without one)
458 void about_button_changelog (GtkWidget *widget, gpointer data)
460 StringOutputStream log(256);
461 log << AppPath_get() << "changelog.txt";
462 OpenURL(log.c_str());
465 void about_button_credits (GtkWidget *widget, gpointer data)
467 StringOutputStream cred(256);
468 cred << AppPath_get() << "credits.html";
469 OpenURL(cred.c_str());
475 ModalDialogButton ok_button(dialog, eIDOK);
477 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "About GtkRadiant", dialog);
480 GtkVBox* vbox = create_dialog_vbox(4, 4);
481 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
484 GtkHBox* hbox = create_dialog_hbox(4);
485 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, TRUE, 0);
488 GtkVBox* vbox2 = create_dialog_vbox(4);
489 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox2), TRUE, FALSE, 0);
491 GtkFrame* frame = create_dialog_frame(0, GTK_SHADOW_IN);
492 gtk_box_pack_start(GTK_BOX (vbox2), GTK_WIDGET(frame), FALSE, FALSE, 0);
494 GtkImage* image = new_local_image("logo.bmp");
495 gtk_widget_show(GTK_WIDGET(image));
496 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(image));
502 GtkLabel* label = GTK_LABEL(gtk_label_new("GtkRadiant " RADIANT_VERSION "\n"
504 RADIANT_ABOUTMSG "\n\n"
505 "By qeradiant.com\n\n"
506 "This product contains software technology\n"
507 "from id Software, Inc. ('id Technology').\n"
508 "id Technology 2000 id Software,Inc.\n\n"
509 "GtkRadiant is unsupported, however\n"
510 "you may report your problems at\n"
511 "http://zerowing.idsoftware.com/bugzilla"
514 gtk_widget_show(GTK_WIDGET(label));
515 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(label), FALSE, FALSE, 0);
516 gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
517 gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
521 GtkVBox* vbox2 = create_dialog_vbox(4);
522 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox2), FALSE, TRUE, 0);
524 GtkButton* button = create_modal_dialog_button("OK", ok_button);
525 gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(button), FALSE, FALSE, 0);
528 GtkButton* button = create_dialog_button("Credits", G_CALLBACK(about_button_credits), 0);
529 gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(button), FALSE, FALSE, 0);
532 GtkButton* button = create_dialog_button("Changelog", G_CALLBACK(about_button_changelog), 0);
533 gtk_box_pack_start (GTK_BOX (vbox2), GTK_WIDGET(button), FALSE, FALSE, 0);
538 GtkFrame* frame = create_dialog_frame("OpenGL Properties");
539 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(frame), FALSE, FALSE, 0);
541 GtkTable* table = create_dialog_table(3, 2, 4, 4, 4);
542 gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(table));
544 GtkLabel* label = GTK_LABEL(gtk_label_new("Vendor:"));
545 gtk_widget_show(GTK_WIDGET(label));
546 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 0, 1,
547 (GtkAttachOptions) (GTK_FILL),
548 (GtkAttachOptions) (0), 0, 0);
549 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
552 GtkLabel* label = GTK_LABEL(gtk_label_new("Version:"));
553 gtk_widget_show(GTK_WIDGET(label));
554 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 1, 2,
555 (GtkAttachOptions) (GTK_FILL),
556 (GtkAttachOptions) (0), 0, 0);
557 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
560 GtkLabel* label = GTK_LABEL(gtk_label_new("Renderer:"));
561 gtk_widget_show(GTK_WIDGET(label));
562 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 2, 3,
563 (GtkAttachOptions) (GTK_FILL),
564 (GtkAttachOptions) (0), 0, 0);
565 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
568 GtkLabel* label = GTK_LABEL(gtk_label_new(reinterpret_cast<const char*>(glGetString(GL_VENDOR))));
569 gtk_widget_show(GTK_WIDGET(label));
570 gtk_table_attach(table, GTK_WIDGET(label), 1, 2, 0, 1,
571 (GtkAttachOptions) (GTK_FILL),
572 (GtkAttachOptions) (0), 0, 0);
573 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
576 GtkLabel* label = GTK_LABEL(gtk_label_new(reinterpret_cast<const char*>(glGetString(GL_VERSION))));
577 gtk_widget_show(GTK_WIDGET(label));
578 gtk_table_attach(table, GTK_WIDGET(label), 1, 2, 1, 2,
579 (GtkAttachOptions) (GTK_FILL),
580 (GtkAttachOptions) (0), 0, 0);
581 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
584 GtkLabel* label = GTK_LABEL(gtk_label_new(reinterpret_cast<const char*>(glGetString(GL_RENDERER))));
585 gtk_widget_show(GTK_WIDGET(label));
586 gtk_table_attach(table, GTK_WIDGET(label), 1, 2, 2, 3,
587 (GtkAttachOptions) (GTK_FILL),
588 (GtkAttachOptions) (0), 0, 0);
589 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
593 GtkFrame* frame = create_dialog_frame("OpenGL Extensions");
594 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(frame), TRUE, TRUE, 0);
596 GtkScrolledWindow* sc_extensions = create_scrolled_window(GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS, 4);
597 gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(sc_extensions));
599 GtkWidget* text_extensions = gtk_text_view_new();
600 gtk_text_view_set_editable(GTK_TEXT_VIEW(text_extensions), FALSE);
601 gtk_container_add (GTK_CONTAINER (sc_extensions), text_extensions);
602 GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_extensions));
603 gtk_text_buffer_set_text(buffer, reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)), -1);
604 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_extensions), GTK_WRAP_WORD);
605 gtk_widget_show(text_extensions);
612 modal_dialog_show(window, dialog);
614 gtk_widget_destroy(GTK_WIDGET(window));
617 // =============================================================================
618 // Texture List dialog
620 void DoTextureListDlg()
623 ModalDialogButton ok_button(dialog, eIDOK);
624 ModalDialogButton cancel_button(dialog, eIDCANCEL);
625 GtkWidget* texture_list;
627 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Textures", dialog, 400, 400);
629 GtkHBox* hbox = create_dialog_hbox(4, 4);
630 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
633 GtkScrolledWindow* scr = create_scrolled_window(GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
634 gtk_box_pack_start(GTK_BOX (hbox), GTK_WIDGET(scr), TRUE, TRUE, 0);
638 GtkListStore* store = gtk_list_store_new(1, G_TYPE_STRING);
640 GtkWidget* view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
641 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
644 GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
645 GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("", renderer, "text", 0, 0);
646 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column);
649 gtk_widget_show(view);
650 gtk_container_add(GTK_CONTAINER (scr), view);
654 GSList *textures = 0;
655 TextureGroupsMenu_ListItems(textures);
656 while (textures != 0)
660 gtk_list_store_append(store, &iter);
661 StringOutputStream name(64);
662 name << ConvertLocaleToUTF8(reinterpret_cast<const char*>(textures->data));
663 gtk_list_store_set(store, &iter, 0, name.c_str(), -1);
665 textures = g_slist_remove (textures, textures->data);
669 g_object_unref(G_OBJECT(store));
675 GtkVBox* vbox = create_dialog_vbox(4);
676 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, TRUE, 0);
678 GtkButton* button = create_modal_dialog_button("Load", ok_button);
679 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
682 GtkButton* button = create_modal_dialog_button("Close", cancel_button);
683 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
686 if(modal_dialog_show(window, dialog) == eIDOK)
688 GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(texture_list));
692 if(gtk_tree_selection_get_selected(selection, &model, &iter))
694 GtkTreePath* path = gtk_tree_model_get_path(model, &iter);
695 if(gtk_tree_path_get_depth(path) == 1)
696 TextureBrowser_ShowDirectory(GlobalTextureBrowser(), TextureGroupsMenu_GetName(gtk_tree_path_get_indices(path)[0]));
697 gtk_tree_path_free(path);
701 gtk_widget_destroy(GTK_WIDGET(window));
704 // =============================================================================
705 // TextureLayout dialog
707 EMessageBoxReturn DoTextureLayout (float *fx, float *fy)
710 ModalDialogButton ok_button(dialog, eIDOK);
711 ModalDialogButton cancel_button(dialog, eIDCANCEL);
715 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Patch texture layout", dialog);
717 GtkAccelGroup* accel = gtk_accel_group_new();
718 gtk_window_add_accel_group(window, accel);
721 GtkHBox* hbox = create_dialog_hbox(4, 4);
722 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
724 GtkVBox* vbox = create_dialog_vbox(4);
725 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
727 GtkLabel* label = GTK_LABEL(gtk_label_new("Texture will be fit across the patch based\n"
728 "on the x and y values given. Values of 1x1\n"
729 "will \"fit\" the texture. 2x2 will repeat\n"
731 gtk_widget_show(GTK_WIDGET(label));
732 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), TRUE, TRUE, 0);
733 gtk_label_set_justify(label, GTK_JUSTIFY_LEFT);
736 GtkTable* table = create_dialog_table(2, 2, 4, 4);
737 gtk_widget_show(GTK_WIDGET(table));
738 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), TRUE, TRUE, 0);
740 GtkLabel* label = GTK_LABEL(gtk_label_new("Texture x:"));
741 gtk_widget_show(GTK_WIDGET(label));
742 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 0, 1,
743 (GtkAttachOptions) (GTK_FILL),
744 (GtkAttachOptions) (0), 0, 0);
745 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
748 GtkLabel* label = GTK_LABEL(gtk_label_new("Texture y:"));
749 gtk_widget_show(GTK_WIDGET(label));
750 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 1, 2,
751 (GtkAttachOptions) (GTK_FILL),
752 (GtkAttachOptions) (0), 0, 0);
753 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
756 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
757 gtk_widget_show(GTK_WIDGET(entry));
758 gtk_table_attach(table, GTK_WIDGET(entry), 1, 2, 0, 1,
759 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
760 (GtkAttachOptions) (0), 0, 0);
762 gtk_widget_grab_focus(GTK_WIDGET(entry));
767 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
768 gtk_widget_show(GTK_WIDGET(entry));
769 gtk_table_attach(table, GTK_WIDGET(entry), 1, 2, 1, 2,
770 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
771 (GtkAttachOptions) (0), 0, 0);
778 GtkVBox* vbox = create_dialog_vbox(4);
779 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
781 GtkButton* button = create_modal_dialog_button("OK", ok_button);
782 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
783 widget_make_default(GTK_WIDGET(button));
784 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
787 GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
788 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
789 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
795 gtk_entry_set_text(x, "4.0");
796 gtk_entry_set_text(y, "4.0");
799 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
802 *fx = static_cast<float>(atof(gtk_entry_get_text(x)));
803 *fy = static_cast<float>(atof(gtk_entry_get_text(y)));
806 gtk_widget_destroy(GTK_WIDGET(window));
811 // =============================================================================
812 // Text Editor dialog
814 // master window widget
815 static GtkWidget *text_editor = 0;
816 static GtkWidget *text_widget; // slave, text widget from the gtk editor
818 static gint editor_delete (GtkWidget *widget, gpointer data)
820 if (gtk_MessageBox (widget, "Close the shader editor ?", "Radiant", eMB_YESNO, eMB_ICONQUESTION) == eIDNO)
823 gtk_widget_hide (text_editor);
828 static void editor_save (GtkWidget *widget, gpointer data)
830 FILE *f = fopen ((char*)g_object_get_data (G_OBJECT (data), "filename"), "w");
831 gpointer text = g_object_get_data (G_OBJECT (data), "text");
835 gtk_MessageBox (GTK_WIDGET(data), "Error saving file !");
839 char *str = gtk_editable_get_chars (GTK_EDITABLE (text), 0, -1);
840 fwrite (str, 1, strlen (str), f);
844 static void editor_close (GtkWidget *widget, gpointer data)
846 if (gtk_MessageBox (text_editor, "Close the shader editor ?", "Radiant", eMB_YESNO, eMB_ICONQUESTION) == eIDNO)
849 gtk_widget_hide (text_editor);
852 static void CreateGtkTextEditor()
855 GtkWidget *vbox, *hbox, *button, *scr, *text;
857 dlg = gtk_window_new (GTK_WINDOW_TOPLEVEL);
859 g_signal_connect(G_OBJECT(dlg), "delete_event",
860 G_CALLBACK(editor_delete), 0);
861 gtk_window_set_default_size (GTK_WINDOW (dlg), 600, 300);
863 vbox = gtk_vbox_new (FALSE, 5);
864 gtk_widget_show (vbox);
865 gtk_container_add(GTK_CONTAINER(dlg), GTK_WIDGET(vbox));
866 gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
868 scr = gtk_scrolled_window_new (0, 0);
869 gtk_widget_show (scr);
870 gtk_box_pack_start(GTK_BOX(vbox), scr, TRUE, TRUE, 0);
871 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scr), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
872 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
874 text = gtk_text_view_new();
875 gtk_container_add (GTK_CONTAINER (scr), text);
876 gtk_widget_show (text);
877 g_object_set_data (G_OBJECT (dlg), "text", text);
878 gtk_text_view_set_editable (GTK_TEXT_VIEW(text), TRUE);
880 hbox = gtk_hbox_new (FALSE, 5);
881 gtk_widget_show (hbox);
882 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(hbox), FALSE, TRUE, 0);
884 button = gtk_button_new_with_label ("Close");
885 gtk_widget_show (button);
886 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
887 g_signal_connect(G_OBJECT(button), "clicked",
888 G_CALLBACK(editor_close), dlg);
889 gtk_widget_set_usize (button, 60, -2);
891 button = gtk_button_new_with_label ("Save");
892 gtk_widget_show (button);
893 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
894 g_signal_connect(G_OBJECT(button), "clicked",
895 G_CALLBACK(editor_save), dlg);
896 gtk_widget_set_usize (button, 60, -2);
902 static void DoGtkTextEditor (const char* filename, guint cursorpos)
905 CreateGtkTextEditor(); // build it the first time we need it
908 FILE *f = fopen (filename, "r");
912 globalOutputStream() << "Unable to load file " << filename << " in shader editor.\n";
913 gtk_widget_hide (text_editor);
917 fseek (f, 0, SEEK_END);
919 void *buf = malloc (len);
923 fread (buf, 1, len, f);
925 gtk_window_set_title (GTK_WINDOW (text_editor), filename);
927 GtkTextBuffer* text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_widget));
928 gtk_text_buffer_set_text(text_buffer, (char*)buf, len);
930 old_filename = g_object_get_data (G_OBJECT (text_editor), "filename");
933 g_object_set_data (G_OBJECT (text_editor), "filename", strdup (filename));
935 // trying to show later
936 gtk_widget_show (text_editor);
942 // only move the cursor if it's not exceeding the size..
943 // NOTE: this is erroneous, cursorpos is the offset in bytes, not in characters
944 // len is the max size in bytes, not in characters either, but the character count is below that limit..
945 // thinking .. the difference between character count and byte count would be only because of CR/LF?
947 GtkTextIter text_iter;
948 // character offset, not byte offset
949 gtk_text_buffer_get_iter_at_offset(text_buffer, &text_iter, cursorpos);
950 gtk_text_buffer_place_cursor(text_buffer, &text_iter);
954 gtk_widget_queue_draw(text_widget);
962 // =============================================================================
963 // Light Intensity dialog
965 EMessageBoxReturn DoLightIntensityDlg (int *intensity)
968 GtkEntry* intensity_entry;
969 ModalDialogButton ok_button(dialog, eIDOK);
970 ModalDialogButton cancel_button(dialog, eIDCANCEL);
972 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Light intensity", dialog, -1, -1);
974 GtkAccelGroup *accel_group = gtk_accel_group_new();
975 gtk_window_add_accel_group(window, accel_group);
978 GtkHBox* hbox = create_dialog_hbox(4, 4);
979 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
981 GtkVBox* vbox = create_dialog_vbox(4);
982 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
984 GtkLabel* label = GTK_LABEL(gtk_label_new("ESC for default, ENTER to validate"));
985 gtk_widget_show(GTK_WIDGET(label));
986 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(label), FALSE, FALSE, 0);
989 GtkEntry* entry = GTK_ENTRY(gtk_entry_new());
990 gtk_widget_show(GTK_WIDGET(entry));
991 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(entry), TRUE, TRUE, 0);
993 gtk_widget_grab_focus(GTK_WIDGET(entry));
995 intensity_entry = entry;
999 GtkVBox* vbox = create_dialog_vbox(4);
1000 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
1003 GtkButton* button = create_modal_dialog_button("OK", ok_button);
1004 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
1005 widget_make_default(GTK_WIDGET(button));
1006 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
1009 GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
1010 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
1011 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
1017 sprintf (buf, "%d", *intensity);
1018 gtk_entry_set_text(intensity_entry, buf);
1020 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
1022 *intensity = atoi (gtk_entry_get_text(intensity_entry));
1024 gtk_widget_destroy(GTK_WIDGET(window));
1031 #include <gdk/gdkwin32.h>
1035 // use the file associations to open files instead of builtin Gtk editor
1036 bool g_TextEditor_useWin32Editor = true;
1038 // custom shader editor
1039 bool g_TextEditor_useCustomEditor = false;
1040 CopiedString g_TextEditor_editorCommand("");
1043 void DoTextEditor (const char* filename, int cursorpos)
1046 if (g_TextEditor_useWin32Editor)
1048 globalOutputStream() << "opening file '" << filename << "' (line " << cursorpos << " info ignored)\n";
1049 ShellExecute((HWND)GDK_WINDOW_HWND (GTK_WIDGET(MainFrame_getWindow())->window), "open", filename, 0, 0, SW_SHOW );
1053 // check if a custom editor is set
1054 if(g_TextEditor_useCustomEditor && !g_TextEditor_editorCommand.empty())
1056 StringOutputStream strEditCommand(256);
1057 strEditCommand << g_TextEditor_editorCommand.c_str() << " \"" << filename << "\"";
1059 globalOutputStream() << "Launching: " << strEditCommand.c_str() << "\n";
1060 // note: linux does not return false if the command failed so it will assume success
1061 if (Q_Exec(0, const_cast<char*>(strEditCommand.c_str()), 0, true) == false)
1063 globalOutputStream() << "Failed to execute " << strEditCommand.c_str() << ", using default\n";
1067 // the command (appeared) to run successfully, no need to do anything more
1073 DoGtkTextEditor (filename, cursorpos);