Просмотр исходного кода

Improve file/folder drag preview on filesystem dock

Added icons for files/folders in drag preview
Fixed folders getting an empty string label
Don't show "1 more file(s)" label instead of the file
Added "more folders" case if moving folders exclusively
Merged drag_files and drag_files_and_dirs to reduce code duplication
Simplified get_drag_data_fw and removed commented out code
MillionOstrich 7 лет назад
Родитель
Сommit
f6ca9d34a2
3 измененных файлов с 54 добавлено и 105 удалено
  1. 38 46
      editor/editor_node.cpp
  2. 1 2
      editor/editor_node.h
  3. 15 57
      editor/filesystem_dock.cpp

+ 38 - 46
editor/editor_node.cpp

@@ -4217,61 +4217,53 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
 	return drag_data;
 }
 
-Variant EditorNode::drag_files(const Vector<String> &p_files, Control *p_from) {
-
-	VBoxContainer *files = memnew(VBoxContainer);
-
-	int max_files = 6;
-
-	for (int i = 0; i < MIN(max_files, p_files.size()); i++) {
-
+Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from) {
+	bool has_folder = false;
+	bool has_file = false;
+	for (int i = 0; i < p_paths.size(); i++) {
+		bool is_folder = p_paths[i].ends_with("/");
+		has_folder |= is_folder;
+		has_file |= !is_folder;
+	}
+
+	int max_rows = 6;
+	int num_rows = p_paths.size() > max_rows ? max_rows - 1 : p_paths.size(); //Don't waste a row to say "1 more file" - list it instead.
+	VBoxContainer *vbox = memnew(VBoxContainer);
+	for (int i = 0; i < num_rows; i++) {
+		HBoxContainer *hbox = memnew(HBoxContainer);
+		TextureRect *icon = memnew(TextureRect);
 		Label *label = memnew(Label);
-		label->set_text(p_files[i].get_file());
-		files->add_child(label);
-	}
-
-	if (p_files.size() > max_files) {
 
-		Label *label = memnew(Label);
-		label->set_text(vformat(TTR("%d more file(s)"), p_files.size() - max_files));
-		files->add_child(label);
+		if (p_paths[i].ends_with("/")) {
+			label->set_text(p_paths[i].substr(0, p_paths[i].length() - 1).get_file());
+			icon->set_texture(gui_base->get_icon("Folder", "EditorIcons"));
+		} else {
+			label->set_text(p_paths[i].get_file());
+			icon->set_texture(gui_base->get_icon("File", "EditorIcons"));
+		}
+		icon->set_size(Size2(16, 16));
+		hbox->add_child(icon);
+		hbox->add_child(label);
+		vbox->add_child(hbox);
 	}
-	Dictionary drag_data;
-	drag_data["type"] = "files";
-	drag_data["files"] = p_files;
-	drag_data["from"] = p_from;
-
-	p_from->set_drag_preview(files); //wait until it enters scene
-
-	return drag_data;
-}
-
-Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_files, Control *p_from) {
-
-	VBoxContainer *files = memnew(VBoxContainer);
-
-	int max_files = 6;
-
-	for (int i = 0; i < MIN(max_files, p_files.size()); i++) {
 
+	if (p_paths.size() > num_rows) {
 		Label *label = memnew(Label);
-		label->set_text(p_files[i].get_file());
-		files->add_child(label);
+		if (has_file && has_folder) {
+			label->set_text(vformat(TTR("%d more files or folders"), p_paths.size() - num_rows));
+		} else if (has_folder) {
+			label->set_text(vformat(TTR("%d more folders"), p_paths.size() - num_rows));
+		} else {
+			label->set_text(vformat(TTR("%d more files"), p_paths.size() - num_rows));
+		}
+		vbox->add_child(label);
 	}
+	p_from->set_drag_preview(vbox); //wait until it enters scene
 
-	if (p_files.size() > max_files) {
-
-		Label *label = memnew(Label);
-		label->set_text(vformat(TTR("%d more file(s) or folder(s)"), p_files.size() - max_files));
-		files->add_child(label);
-	}
 	Dictionary drag_data;
-	drag_data["type"] = "files_and_dirs";
-	drag_data["files"] = p_files;
+	drag_data["type"] = has_folder ? "files_and_dirs" : "files";
+	drag_data["files"] = p_paths;
 	drag_data["from"] = p_from;
-
-	p_from->set_drag_preview(files); //wait until it enters scene
-
 	return drag_data;
 }
 

+ 1 - 2
editor/editor_node.h

@@ -765,8 +765,7 @@ public:
 	void remove_bottom_panel_item(Control *p_item);
 
 	Variant drag_resource(const Ref<Resource> &p_res, Control *p_from);
-	Variant drag_files(const Vector<String> &p_files, Control *p_from);
-	Variant drag_files_and_dirs(const Vector<String> &p_files, Control *p_from);
+	Variant drag_files_and_dirs(const Vector<String> &p_paths, Control *p_from);
 
 	void add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud = Variant());
 	void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu);

+ 15 - 57
editor/filesystem_dock.cpp

@@ -1186,78 +1186,36 @@ void FileSystemDock::set_display_mode(int p_mode) {
 }
 
 Variant FileSystemDock::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
+	bool is_favorite = false;
+	Vector<String> paths;
 
 	if (p_from == tree) {
-
 		TreeItem *selected = tree->get_selected();
 		if (!selected)
 			return Variant();
 
-		String fpath = selected->get_metadata(0);
-		if (fpath == String())
+		String folder = selected->get_metadata(0);
+		if (folder == String())
 			return Variant();
-		if (!fpath.ends_with("/"))
-			fpath = fpath + "/";
-		Vector<String> paths;
-		paths.push_back(fpath);
-		Dictionary d = EditorNode::get_singleton()->drag_files(paths, p_from);
-
-		if (selected->get_parent() && tree->get_root()->get_children() == selected->get_parent()) {
-			//a favorite.. treat as such
-			d["type"] = "favorite";
-		}
-
-		return d;
-	}
-
-	if (p_from == files) {
-
-		List<int> seldirs;
-		List<int> selfiles;
 
+		paths.push_back(folder.ends_with("/") ? folder : (folder + "/"));
+		is_favorite = selected->get_parent() != NULL && tree->get_root()->get_children() == selected->get_parent();
+	} else if (p_from == files) {
 		for (int i = 0; i < files->get_item_count(); i++) {
 			if (files->is_selected(i)) {
-				String fpath = files->get_item_metadata(i);
-				if (fpath.ends_with("/"))
-					seldirs.push_back(i);
-				else
-					selfiles.push_back(i);
+				paths.push_back(files->get_item_metadata(i));
 			}
 		}
+	}
 
-		if (seldirs.empty() && selfiles.empty())
-			return Variant();
-		/*
-		if (seldirs.size() && selfiles.size())
-			return Variant(); //can't really mix files and dirs (i think?) - yes you can, commenting
-		*/
-
-		/*if (selfiles.size()==1) {
-			Ref<Resource> resource = ResourceLoader::load(files->get_item_metadata(selfiles.front()->get()));
-			if (resource.is_valid()) {
-				return EditorNode::get_singleton()->drag_resource(resource,p_from);
-			}
-		}*/
-
-		Vector<String> fnames;
-		if (selfiles.size() > 0 || seldirs.size() > 0) {
-			if (selfiles.size() > 0) {
-				for (List<int>::Element *E = selfiles.front(); E; E = E->next()) {
-					fnames.push_back(files->get_item_metadata(E->get()));
-				}
-				if (seldirs.size() == 0)
-					return EditorNode::get_singleton()->drag_files(fnames, p_from);
-			}
-
-			for (List<int>::Element *E = seldirs.front(); E; E = E->next()) {
-				fnames.push_back(files->get_item_metadata(E->get()));
-			}
+	if (paths.empty())
+		return Variant();
 
-			return EditorNode::get_singleton()->drag_files_and_dirs(fnames, p_from);
-		}
+	Dictionary drag_data = EditorNode::get_singleton()->drag_files_and_dirs(paths, p_from);
+	if (is_favorite) {
+		drag_data["type"] = "favorite";
 	}
-
-	return Variant();
+	return drag_data;
 }
 
 bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {