Repository: godotengine/godot
File: editor/scene/sprite_frames_editor_plugin.cpp (C++)

Code before:
			empty_after->set_button_icon(get_editor_theme_icon(SNAME("InsertAfter")));
			move_up->set_button_icon(get_editor_theme_icon(SNAME("MoveLeft")));
			move_down->set_button_icon(get_editor_theme_icon(SNAME("MoveRight")));
			delete_frame->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
			zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess")));
			zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset")));
			zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore")));
			add_anim->set_button_icon(get_editor_theme_icon(SNAME("New")));
			duplicate_anim->set_button_icon(get_editor_theme_icon(SNAME("Duplicate")));
			delete_anim->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
			anim_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
			split_sheet_zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess")));
			split_sheet_zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset")));
			split_sheet_zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore")));
			split_sheet_scroll->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));

			_update_show_settings();
		} break;

		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
		case NOTIFICATION_TRANSLATION_CHANGED: {
			_update_show_settings();

			anim_speed->set_suffix(TTR("FPS"));

			// Same as in `_update_library_impl()`, but update names only for items without texture.
			if (frames.is_valid()) {
				for (int i = 0; i < frames->get_frame_count(edited_anim); i++) {
					Ref<Texture2D> texture = frames->get_frame_texture(edited_anim, i);
					if (texture.is_null()) {
						String name = itos(i);
						float duration = frames->get_frame_duration(edited_anim, i);
						texture = empty_icon;
						name += ": " + TTR("(empty)");
						if (duration != 1.0f) {
							name += String::utf8(" [× ") + String::num(duration, 2) + "]";
						}
						frame_list->set_item_text(i, name);
					}
				}
			}
		} break;

		case NOTIFICATION_READY: {
			add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
		} break;

		case NOTIFICATION_EXIT_TREE: {
			get_tree()->disconnect("node_removed", callable_mp(this, &SpriteFramesEditor::_node_removed));
		} break;
	}

Review comment (refactor):
If it's the same, the code should be extracted to a new method, to avoid duplicating logic. It's fine if the common method can't separate frames with and without texture.

Code after:
			empty_after->set_button_icon(get_editor_theme_icon(SNAME("InsertAfter")));
			move_up->set_button_icon(get_editor_theme_icon(SNAME("MoveLeft")));
			move_down->set_button_icon(get_editor_theme_icon(SNAME("MoveRight")));
			delete_frame->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
			zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess")));
			zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset")));
			zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore")));
			add_anim->set_button_icon(get_editor_theme_icon(SNAME("New")));
			duplicate_anim->set_button_icon(get_editor_theme_icon(SNAME("Duplicate")));
			delete_anim->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
			anim_search_box->set_right_icon(get_editor_theme_icon(SNAME("Search")));
			split_sheet_zoom_out->set_button_icon(get_editor_theme_icon(SNAME("ZoomLess")));
			split_sheet_zoom_reset->set_button_icon(get_editor_theme_icon(SNAME("ZoomReset")));
			split_sheet_zoom_in->set_button_icon(get_editor_theme_icon(SNAME("ZoomMore")));
			split_sheet_scroll->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));

			_update_show_settings();
		} break;

		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
			_update_show_settings();
		} break;

		case NOTIFICATION_TRANSLATION_CHANGED: {
			_update_show_settings();
			anim_speed->set_suffix(TTR("FPS"));

			// Similar to `_update_library_impl()`, but only updates text for "empty" items.
			if (frames.is_valid()) {
				for (int i = 0; i < frames->get_frame_count(edited_anim); i++) {
					Ref<Texture2D> texture = frames->get_frame_texture(edited_anim, i);
					if (texture.is_null()) {
						String name = itos(i);
						float duration = frames->get_frame_duration(edited_anim, i);
						texture = empty_icon;
						name += ": " + TTR("(empty)");
						if (duration != 1.0f) {
							name += String::utf8(" [× ") + String::num(duration, 2) + "]";
						}
						frame_list->set_item_text(i, name);
					}
				}
			}
		} break;

		case NOTIFICATION_READY: {
			add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
		} break;

		case NOTIFICATION_EXIT_TREE: {
			get_tree()->disconnect("node_removed", callable_mp(this, &SpriteFramesEditor::_node_removed));