object_editor.vala 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright (c) 2012-2026 Daniele Bartolini et al.
  3. * SPDX-License-Identifier: GPL-3.0-or-later
  4. */
  5. namespace Crown
  6. {
  7. public class ObjectEditor : Gtk.ApplicationWindow
  8. {
  9. public DatabaseEditor _database_editor;
  10. public Database _database;
  11. public ObjectTree _objects_tree;
  12. public ObjectProperties _objects_properties;
  13. public Gtk.Paned _paned;
  14. public Statusbar _statusbar;
  15. public Gtk.Button _cancel;
  16. public Gtk.Button _save;
  17. public Gtk.HeaderBar _header_bar;
  18. public Gtk.Box _box;
  19. public string _object_name;
  20. public Guid _object_id;
  21. public signal void saved();
  22. public ObjectEditor(Gtk.Application application
  23. , Project project
  24. , uint32 undo_redo_size
  25. )
  26. {
  27. Object(application: application);
  28. _object_id = GUID_ZERO;
  29. _database_editor = new DatabaseEditor(project, undo_redo_size);
  30. _database_editor.undo.connect(on_undo);
  31. _database_editor.redo.connect(on_redo);
  32. this.insert_action_group("database", _database_editor._action_group);
  33. _database = _database_editor._database;
  34. _database.objects_created.connect(on_objects_created);
  35. _database.objects_destroyed.connect(on_objects_destroyed);
  36. _database.objects_changed.connect(on_objects_changed);
  37. _objects_tree = new ObjectTree(_database_editor);
  38. _objects_properties = new ObjectProperties(_database_editor);
  39. _database_editor.load_types();
  40. _statusbar = new Statusbar();
  41. _cancel = new Gtk.Button.with_label("Cancel");
  42. _cancel.clicked.connect(() => {
  43. close();
  44. });
  45. _save = new Gtk.Button.with_label("Save & Reload");
  46. _save.get_style_context().add_class("suggested-action");
  47. _save.clicked.connect(save);
  48. _header_bar = new Gtk.HeaderBar();
  49. _header_bar.title = "Object Editor";
  50. _header_bar.show_close_button = true;
  51. _header_bar.pack_start(_cancel);
  52. _header_bar.pack_end(_save);
  53. _paned = new Gtk.Paned(Gtk.Orientation.HORIZONTAL);
  54. _paned.pack1(_objects_tree, true, false);
  55. _paned.pack2(_objects_properties, true, false);
  56. this.set_titlebar(_header_bar);
  57. this.set_size_request(1000, 600);
  58. int win_w;
  59. int win_h;
  60. this.get_size(out win_w, out win_h);
  61. _paned.set_position(win_w/2);
  62. GLib.Menu menu = new GLib.Menu();
  63. GLib.MenuItem mi = null;
  64. mi = new GLib.MenuItem("Edit", null);
  65. mi.set_submenu(make_database_editor_menu());
  66. menu.append_item(mi);
  67. this.show_menubar = false;
  68. Gtk.MenuBar menubar = new Gtk.MenuBar.from_model(menu);
  69. _box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
  70. _box.pack_start(menubar, false);
  71. _box.pack_start(_paned);
  72. _box.pack_start(_statusbar, false);
  73. this.delete_event.connect(on_close_request);
  74. this.add(_box);
  75. reset();
  76. }
  77. public void update_window_title()
  78. {
  79. string title = "";
  80. if (_database.changed())
  81. title += " • ";
  82. title += _object_id == GUID_ZERO ? "unnamed" : _object_name;
  83. title += " - ";
  84. title += CROWN_EDITOR_NAME;
  85. if (this.title != title)
  86. this.title = title;
  87. }
  88. public void reset()
  89. {
  90. _database.reset();
  91. _object_name = "";
  92. _object_id = GUID_ZERO;
  93. }
  94. public void save()
  95. {
  96. assert(_object_id != GUID_ZERO);
  97. ObjectTypeInfo info = _database.type_info(StringId64(_database.object_type(_object_id)));
  98. if (_database.save(_database._project.absolute_path(_object_name) + "." + info.name, _object_id) == 0)
  99. saved();
  100. }
  101. public void on_objects_created(Guid?[] object_ids, uint32 flags)
  102. {
  103. Guid last_created = object_ids[object_ids.length - 1];
  104. _objects_tree.set_object(_object_id); // Force update the tree.
  105. _database_editor.selection_set({ last_created }); // Select the objects just created.
  106. update_window_title();
  107. }
  108. public void on_objects_destroyed(Guid?[] object_ids, uint32 flags = 0)
  109. {
  110. _objects_tree.set_object(_object_id); // Force update the tree.
  111. _database_editor.selection_set({ _object_id }); // Select the root object which must always exits.
  112. update_window_title();
  113. }
  114. public void on_objects_changed(Guid?[] object_ids, uint32 flags = 0)
  115. {
  116. Guid last_changed = object_ids[object_ids.length - 1];
  117. _objects_tree.set_object(_object_id); // Force update the tree.
  118. _database_editor.selection_set({ last_changed });
  119. update_window_title();
  120. }
  121. public void do_set_object(string type, string name)
  122. {
  123. reset();
  124. string resource_path = ResourceId.path(type, name);
  125. string path = _database._project.absolute_path(resource_path);
  126. if (_database.load_from_path(out _object_id, path, resource_path) != 0)
  127. return;
  128. _object_name = name;
  129. _objects_tree.set_object(_object_id);
  130. _database_editor.selection_set({ _object_id });
  131. update_window_title();
  132. }
  133. public void set_object(string type, string name)
  134. {
  135. if (_object_name == name)
  136. return;
  137. if (!_database.changed()) {
  138. this.do_set_object(type, name);
  139. } else {
  140. Gtk.Dialog dlg = new_resource_changed_dialog(this, _object_name);
  141. dlg.response.connect((response_id) => {
  142. if (response_id == Gtk.ResponseType.NO) {
  143. this.do_set_object(type, name);
  144. } else if (response_id == Gtk.ResponseType.YES) {
  145. this.save();
  146. this.do_set_object(type, name);
  147. }
  148. dlg.destroy();
  149. });
  150. dlg.show_all();
  151. }
  152. }
  153. public void on_objects_tree_selection_changed(Guid?[] objects)
  154. {
  155. _database_editor.selection_read(objects);
  156. }
  157. public void on_undo(int action_id)
  158. {
  159. _statusbar.set_temporary_message("Undo: " + ActionNames[action_id]);
  160. }
  161. public void on_redo(int action_id)
  162. {
  163. _statusbar.set_temporary_message("Redo: " + ActionNames[action_id]);
  164. }
  165. public bool on_close_request(Gdk.EventAny event)
  166. {
  167. this.hide();
  168. return Gdk.EVENT_STOP;
  169. }
  170. }
  171. } /* namespace Crown */