BsLinuxBrowseDialogs.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Utility/BsEditorUtility.h"
  4. #include <gtk/gtk.h>
  5. #include <String/BsUnicode.h>
  6. namespace bs
  7. {
  8. // Note: Code below is the only reason we depend on GTK. Ideally we replace the GTK file dialog with built-in file
  9. // dialog that can be used transparently across platforms, in which case we can also drop GTK.
  10. bool EditorUtility::openBrowseDialog(FileDialogType type, const Path& defaultPath, const String& filterList,
  11. Vector<Path>& paths)
  12. {
  13. static bool gtkInitialized = false;
  14. if(!gtkInitialized)
  15. {
  16. gtk_init(nullptr, nullptr);
  17. gtkInitialized = true;
  18. }
  19. GtkWidget* fakeParent = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  20. const char* titleString;
  21. const char* cancelString;
  22. const char* acceptString;
  23. GtkFileChooserAction action;
  24. if(((int)type & (int)FileDialogType::OpenFile) != 0)
  25. {
  26. titleString = "Open File";
  27. cancelString = "Cancel";
  28. acceptString = "Open";
  29. action = GTK_FILE_CHOOSER_ACTION_OPEN;
  30. }
  31. else if(((int)type & (int)FileDialogType::OpenFolder) != 0)
  32. {
  33. titleString = "Open Folder";
  34. cancelString = "Cancel";
  35. acceptString = "Open";
  36. action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
  37. }
  38. else // Save dialog
  39. {
  40. titleString = "Save File";
  41. cancelString = "Cancel";
  42. acceptString = "Save";
  43. action = GTK_FILE_CHOOSER_ACTION_SAVE;
  44. }
  45. GtkWidget* fileDialog = gtk_file_chooser_dialog_new(titleString,
  46. GTK_WINDOW(fakeParent), action, cancelString, GTK_RESPONSE_CANCEL,
  47. acceptString, GTK_RESPONSE_ACCEPT, nullptr);
  48. GtkFileChooser* chooser = GTK_FILE_CHOOSER(fileDialog);
  49. gboolean selectMultiple = ((int)type & (int)FileDialogType::Multiselect) != 0;
  50. gtk_file_chooser_set_select_multiple(chooser, selectMultiple);
  51. gtk_file_chooser_set_do_overwrite_confirmation(chooser, true);
  52. String defaultPathStr = defaultPath.toString();
  53. if(!defaultPathStr.empty())
  54. gtk_file_chooser_set_current_folder(chooser, defaultPathStr.c_str());
  55. if(!filterList.empty())
  56. {
  57. GtkFileFilter* fileFilter = gtk_file_filter_new();
  58. gtk_file_filter_set_name(fileFilter, filterList.c_str());
  59. gtk_file_filter_add_pattern(fileFilter, filterList.c_str());
  60. gtk_file_chooser_add_filter(chooser, fileFilter);
  61. }
  62. // TODO - Can't set transient-for because the windows belong to two different X11 displays. I'd have to use gtk
  63. // display as the primary display (which is too awkward to be worth it)
  64. //GdkDisplay* gdkDisplay = gdk_x11_lookup_xdisplay(x11display);// gtk_widget_get_display(fileDialog);;
  65. //GdkWindow* parentWindow = gdk_x11_window_foreign_new_for_display(gdkDisplay, xParent);
  66. //gdk_window_set_transient_for(gtk_widget_get_window(fileDialog), parentWindow);
  67. gint response = gtk_dialog_run(GTK_DIALOG(fileDialog));
  68. if(response == GTK_RESPONSE_ACCEPT)
  69. {
  70. GSList* filenames = gtk_file_chooser_get_filenames(chooser);
  71. guint numElems = g_slist_length(filenames);
  72. for(guint i = 0; i < numElems; ++i)
  73. {
  74. char* filename = (char*)g_slist_nth_data(filenames, i);
  75. paths.push_back(String(filename));
  76. g_free(filename);
  77. }
  78. g_slist_free(filenames);
  79. }
  80. gtk_widget_destroy(fileDialog);
  81. gtk_widget_destroy(fakeParent);
  82. // Make sure the destroy events are processed
  83. while(gtk_events_pending())
  84. gtk_main_iteration();
  85. return response == GTK_RESPONSE_ACCEPT;
  86. }
  87. }