panel_new_project.vala 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Copyright (c) 2012-2025 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: GPL-3.0-or-later
  4. */
  5. namespace Crown
  6. {
  7. public class PanelNewProject : Gtk.Box
  8. {
  9. // Data
  10. User _user;
  11. Project _project;
  12. // Widgets
  13. public Gtk.Label _new_project_label;
  14. public Gtk.Label _name_label;
  15. public InputString _entry_name;
  16. public Gtk.Label _create_folder_label;
  17. public Gtk.CheckButton _create_folder;
  18. public Gtk.Label _location_label;
  19. public InputFile _file_chooser_button_location;
  20. public Gtk.Label _template_label;
  21. public InputEnum _combo_box_map_template;
  22. public Gtk.Label _label_message;
  23. public Gtk.Button _button_back;
  24. public Gtk.Button _button_create;
  25. public Gtk.Box _buttons_box;
  26. public Gtk.Box _box;
  27. public Gtk.Grid _grid;
  28. public Clamp _clamp;
  29. public PanelNewProject(User user, Project project)
  30. {
  31. Object(orientation: Gtk.Orientation.VERTICAL);
  32. // Data
  33. _user = user;
  34. _project = project;
  35. _new_project_label = new Gtk.Label(null);
  36. _new_project_label.xalign = 0;
  37. _new_project_label.set_markup("<span font_weight=\"bold\" size=\"x-large\">New Project</span>");
  38. _name_label = new Gtk.Label("Name");
  39. _name_label.xalign = 1;
  40. _entry_name = new InputString();
  41. _location_label = new Gtk.Label("Location");
  42. _location_label.xalign = 1;
  43. _file_chooser_button_location = new InputFile(Gtk.FileChooserAction.SELECT_FOLDER);
  44. _file_chooser_button_location.value = _documents_dir.get_path();
  45. _create_folder_label = new Gtk.Label("Create Project Folder");
  46. _create_folder_label.xalign = 1;
  47. _create_folder = new Gtk.CheckButton();
  48. _create_folder.active = true;
  49. _template_label = new Gtk.Label("Template");
  50. _template_label.xalign = 1;
  51. _combo_box_map_template = new InputEnum();
  52. _combo_box_map_template.hexpand = true;
  53. _combo_box_map_template.append("", "None");
  54. _combo_box_map_template.value = "";
  55. _label_message = new Gtk.Label("");
  56. _label_message.xalign = 1;
  57. _button_back = new Gtk.Button.with_label("Back");
  58. _button_back.clicked.connect(() => {
  59. var app = (LevelEditorApplication)GLib.Application.get_default();
  60. app.show_panel("panel_welcome", Gtk.StackTransitionType.SLIDE_UP);
  61. });
  62. _button_create = new Gtk.Button.with_label("Create");
  63. _button_create.get_style_context().add_class("suggested-action");
  64. _button_create.clicked.connect(() => {
  65. if (_entry_name.text == "") {
  66. _label_message.label = "Choose project name";
  67. return;
  68. }
  69. string? source_dir = _file_chooser_button_location.value;
  70. if (source_dir == null) {
  71. _label_message.label = "Location is not valid";
  72. return;
  73. }
  74. if (_create_folder.active) {
  75. string name = (string)_entry_name.text;
  76. name = name.down();
  77. name = name.replace(" ", "_");
  78. name = name.replace("\f", "_");
  79. name = name.replace("\n", "_");
  80. name = name.replace("\r", "_");
  81. name = name.replace("\t", "_");
  82. name = name.replace("\v", "_");
  83. try {
  84. GLib.File project_folder = GLib.File.new_for_path(Path.build_filename(source_dir, name));
  85. project_folder.make_directory();
  86. source_dir = project_folder.get_path();
  87. } catch (GLib.Error e) {
  88. if (e.code == GLib.IOError.EXISTS)
  89. _label_message.label = "Project Folder already exists";
  90. else
  91. _label_message.label = "Project Folder cannot be created automatically";
  92. return;
  93. }
  94. } else {
  95. if (GLib.FileUtils.test(source_dir, FileTest.IS_REGULAR)) {
  96. _label_message.label = "Location must be an empty directory";
  97. return;
  98. }
  99. if (!is_directory_empty(source_dir)) {
  100. _label_message.label = "Location must be an empty directory";
  101. return;
  102. }
  103. }
  104. _label_message.label = "";
  105. _user.add_or_touch_recent_project(source_dir, _entry_name.text);
  106. var app = (LevelEditorApplication)GLib.Application.get_default();
  107. app.show_panel("main_vbox");
  108. if (_combo_box_map_template.value == "")
  109. _project.create_initial_files(source_dir);
  110. else
  111. copy_template_to_source_dir(source_dir, _combo_box_map_template.value);
  112. app.restart_backend.begin(source_dir, LEVEL_NONE);
  113. });
  114. _buttons_box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 0);
  115. _buttons_box.spacing = 6;
  116. _buttons_box.pack_end(_button_create, false, true);
  117. _buttons_box.pack_end(_button_back, false, true);
  118. _grid = new Gtk.Grid();
  119. _grid.hexpand = true;
  120. _grid.row_spacing = 6;
  121. _grid.column_spacing = 12;
  122. _grid.attach(_name_label, 0, 0);
  123. _grid.attach(_entry_name, 1, 0);
  124. _grid.attach(_create_folder_label, 0, 1);
  125. _grid.attach(_create_folder, 1, 1);
  126. _grid.attach(_location_label, 0, 2);
  127. _grid.attach(_file_chooser_button_location, 1, 2);
  128. _grid.attach(_template_label, 0, 3);
  129. _grid.attach(_combo_box_map_template, 1, 3);
  130. _grid.attach(_buttons_box, 1, 4);
  131. _box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
  132. _box.margin_start = 12;
  133. _box.margin_end = 12;
  134. _box.margin_top = 32;
  135. _box.margin_bottom = 32;
  136. _box.spacing = 12;
  137. _box.pack_start(_new_project_label, false, true);
  138. _box.pack_start(_grid, false, true);
  139. _box.pack_start(_label_message, false, true);
  140. _clamp = new Clamp();
  141. _clamp.set_child(_box);
  142. this.add(_clamp);
  143. }
  144. public void fill_templates_list(string path)
  145. {
  146. GLib.File file = GLib.File.new_for_path(path);
  147. try {
  148. FileEnumerator enumerator = file.enumerate_children("standard::*"
  149. , FileQueryInfoFlags.NOFOLLOW_SYMLINKS
  150. );
  151. for (GLib.FileInfo? info = enumerator.next_file(); info != null ; info = enumerator.next_file()) {
  152. GLib.File source_dir = GLib.File.new_for_path(GLib.Path.build_filename(path, info.get_name()));
  153. _combo_box_map_template.append(source_dir.get_path(), info.get_name());
  154. }
  155. } catch (GLib.Error e) {
  156. loge(e.message);
  157. }
  158. }
  159. public void copy_recursive(GLib.File dst, GLib.File src, GLib.FileCopyFlags flags = GLib.FileCopyFlags.NONE)
  160. {
  161. try {
  162. GLib.FileType src_type = src.query_file_type(GLib.FileQueryInfoFlags.NONE);
  163. if (src_type == GLib.FileType.DIRECTORY) {
  164. if (dst.query_exists() == false)
  165. dst.make_directory();
  166. string dst_path = dst.get_path();
  167. string src_path = src.get_path();
  168. GLib.FileEnumerator enum = src.enumerate_children(GLib.FileAttribute.STANDARD_NAME, GLib.FileQueryInfoFlags.NONE);
  169. for (GLib.FileInfo? info = enum.next_file(); info != null; info = enum.next_file()) {
  170. copy_recursive(GLib.File.new_for_path(GLib.Path.build_filename(dst_path, info.get_name()))
  171. , GLib.File.new_for_path(GLib.Path.build_filename(src_path, info.get_name()))
  172. , flags
  173. );
  174. }
  175. } else if (src_type == GLib.FileType.REGULAR) {
  176. src.copy(dst, flags);
  177. }
  178. } catch (Error e) {
  179. loge(e.message);
  180. }
  181. }
  182. public void copy_template_to_source_dir(string source_dir, string template_dir)
  183. {
  184. GLib.File dst = GLib.File.new_for_path(source_dir);
  185. GLib.File src = GLib.File.new_for_path(template_dir);
  186. copy_recursive(dst, src);
  187. }
  188. }
  189. } /* namespace Crown */