From 81fe8b7e1560eadbbf16404dfde0f7a8183903ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tine=20Podlun=C5=A1ek?= Date: Wed, 25 Sep 2024 14:47:06 +0200 Subject: [PATCH 1/5] Extended search feature to names of scenes, groups, objects, looks, and sounds --- .../catrobat/catroid/test/ui/SearchTest.kt | 210 ++++++++++++++++++ .../catrobat/catroid/ui/BaseFinderFragment.kt | 161 ++++++++++++++ .../catroid/ui/{ScriptFinder.kt => Finder.kt} | 203 +++++++++++------ .../catrobat/catroid/ui/FinderDataManager.kt | 102 +++++++++ .../catrobat/catroid/ui/SpriteActivity.java | 8 - .../ui/recyclerview/adapter/LookAdapter.kt | 6 + .../adapter/MultiViewSpriteAdapter.java | 46 +++- .../ui/recyclerview/adapter/SceneAdapter.java | 10 + .../ui/recyclerview/adapter/SoundAdapter.kt | 7 + .../recyclerview/adapter/SpriteAdapter.java | 1 + .../recyclerview/fragment/LookListFragment.kt | 17 +- .../fragment/RecyclerViewFragment.java | 26 +++ .../fragment/SceneListFragment.kt | 85 ++++++- .../recyclerview/fragment/ScriptFragment.java | 112 +++++++--- .../fragment/SoundListFragment.kt | 19 +- .../fragment/SpriteListFragment.kt | 166 +++++++++++++- .../main/res/layout/fragment_list_view.xml | 50 +++-- .../src/main/res/layout/fragment_script.xml | 2 +- .../layout/view_holder_background_sprite.xml | 6 +- .../main/res/menu/menu_project_activity.xml | 5 + 20 files changed, 1100 insertions(+), 142 deletions(-) create mode 100644 catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt create mode 100644 catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt rename catroid/src/main/java/org/catrobat/catroid/ui/{ScriptFinder.kt => Finder.kt} (53%) create mode 100644 catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt diff --git a/catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt b/catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt new file mode 100644 index 00000000000..fea2558bc5e --- /dev/null +++ b/catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt @@ -0,0 +1,210 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2025 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.test.ui +import android.view.KeyEvent +import androidx.recyclerview.widget.RecyclerView +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers.assertThat +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.catrobat.catroid.ProjectManager +import org.catrobat.catroid.R +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.ui.FinderDataManager +import org.catrobat.catroid.ui.MainMenuActivity +import org.catrobat.catroid.uiespresso.ui.fragment.actionutils.ActionUtils +import org.hamcrest.Matchers.`is` +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.catrobat.catroid.content.Script +import org.catrobat.catroid.content.StartScript +import org.catrobat.catroid.content.bricks.FinishStageBrick + +@RunWith(AndroidJUnit4::class) +class SearchTest { + var projectName = "searchTestProject" + private val projectManager = ProjectManager.getInstance() + + @Rule + @JvmField + var baseActivityTestRule = ActivityScenarioRule(MainMenuActivity::class.java) + private lateinit var script: Script + + @Before + fun setUp() { + createProject(projectName) + } + + @Test + fun testSearchMixed() { + val queryString = "test" + val expectedResults = arrayOf("testsprite2","finish tests","testlook3","testlook4", + "testsound3","testsound4","testsprite3","testscene2", + "testsprite5","testscene3") + Espresso.onView(withId(R.id.myProjectsTextView)).perform(click()) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + + Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation() + .targetContext) + Espresso.onView(withText(R.string.search)).perform(click()) + + Espresso.onView(withId(R.id.search_bar)).perform(click()) + + val viewMatcher = Espresso.onView(withId(R.id.search_bar)).perform( + ViewActions.replaceText(queryString) + ) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + viewMatcher.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) + + for (i in expectedResults.indices) { + val currentFoundName = FinderDataManager.instance.getSearchResultsNames()?.get(i) + assertThat(currentFoundName, `is`(expectedResults[i])) + Espresso.onView(withId(R.id.find_next)).perform(click()) + } + for (i in expectedResults.indices.last downTo 0) { + val currentFoundName = FinderDataManager.instance.getSearchResultsNames()?.get(i) + assertThat(currentFoundName, `is`(expectedResults[i])) + Espresso.onView(withId(R.id.find_previous)).perform(click()) + } + } + + @Test + fun testSceneNotFindableOnLowerLevel(){ + + val queryString = "scene1" + + Espresso.onView(withId(R.id.myProjectsTextView)).perform(click()) + + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + + Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().targetContext) + Espresso.onView(withText(R.string.search)).perform(click()) + Espresso.onView(withId(R.id.search_bar)).perform(click()) + + val viewMatcher = Espresso.onView(withId(R.id.search_bar)).perform( + ViewActions.replaceText(queryString) + ) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + viewMatcher.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) + + assertThat(FinderDataManager.instance.currentMatchIndex, `is` (-1)) + } + @Test + fun testSpriteNotFindableOnLowerLevel(){ + + val queryString = "sprite" + + Espresso.onView(withId(R.id.myProjectsTextView)).perform(click()) + + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + + Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().targetContext) + Espresso.onView(withText(R.string.search)).perform(click()) + Espresso.onView(withId(R.id.search_bar)).perform(click()) + + val viewMatcher = Espresso.onView(withId(R.id.search_bar)).perform( + ViewActions.replaceText(queryString) + ) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + viewMatcher.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) + + assertThat(FinderDataManager.instance.currentMatchIndex, `is` (-1)) + } + + fun createProject(projectName: String?) { + val project = Project(ApplicationProvider.getApplicationContext(), projectName) + projectManager.currentProject = project + project.sceneList.clear() + val scene1Name = "scene1" + val scene2Name = "testScene2" + val scene3Name = "testScene3" + val scene4Name = "scene4" + + val scene1 = Scene(scene1Name, project) + val scene2 = Scene(scene2Name, project) + val scene3 = Scene(scene3Name, project) + val scene4 = Scene(scene4Name, project) + val sprite1 = Sprite("background") + val sprite2 = Sprite("testSprite2") + val sprite3 = Sprite("testSprite3") + val sprite4 = Sprite("background") + val sprite5 = Sprite("testSprite5") + project.addScene(scene1) + project.addScene(scene2) + project.addScene(scene3) + project.addScene(scene4) + project.getSceneByName(scene1Name).addSprite(sprite1) + project.getSceneByName(scene1Name).addSprite(sprite2) + project.getSceneByName(scene1Name).addSprite(sprite3) + project.getSceneByName(scene2Name).addSprite(sprite4) + project.getSceneByName(scene2Name).addSprite(sprite5) + + projectManager.apply { + setCurrentSceneAndSprite(scene1Name, sprite2.name) + currentSprite = sprite2 // Force update + currentlyEditedScene = project.getSceneByName(scene1Name) + } + + script = StartScript() + script.addBrick(FinishStageBrick()) + projectManager.currentSprite.addScript(script) + + ActionUtils.addSound(projectManager,"testSound3") + ActionUtils.addSound(projectManager, "Sound3") + ActionUtils.addSound(projectManager,"testSound4") + ActionUtils.addSound(projectManager, "Sound4") + ActionUtils.addLook(projectManager,"testLook3") + ActionUtils.addLook(projectManager, "Look3") + ActionUtils.addLook(projectManager,"testLook4") + ActionUtils.addLook(projectManager, "Look4") + + ProjectManager.getInstance().currentProject = project + } +} \ No newline at end of file diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt new file mode 100644 index 00000000000..05dd9fbd93c --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt @@ -0,0 +1,161 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2025 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.ui + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.TextView +import org.catrobat.catroid.ProjectManager +import org.catrobat.catroid.R +import org.catrobat.catroid.common.Nameable +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.ui.recyclerview.fragment.RecyclerViewFragment +import org.koin.android.ext.android.inject + +abstract class BaseFinderFragment : RecyclerViewFragment() { + + protected val projectManager: ProjectManager by inject() + protected lateinit var currentProject: Project + protected lateinit var currentScene: Scene + protected lateinit var currentSprite: Sprite + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val parentView = super.onCreateView(inflater, container, savedInstanceState) + activity = getActivity() as SpriteActivity? + recyclerView = parentView!!.findViewById(R.id.recycler_view) + currentProject = projectManager.currentProject + currentScene = projectManager.currentlyEditedScene + currentSprite = projectManager.currentSprite + + setupFinderListeners() + + if (FinderDataManager.instance.getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + val sceneAndSpriteName = createActionBarTitle(1) + finder?.onFragmentChanged(sceneAndSpriteName) + scrollToSearchResult() + } + + return parentView + } + + private fun setupFinderListeners() { + finder?.setOnResultFoundListener(object : Finder.OnResultFoundListener { + override fun onResultFound( + sceneIndex: Int, + spriteIndex: Int, + brickIndex: Int, + type: Int, + totalResults: Int, + textView: TextView? + ) { + currentProject = projectManager.currentProject + currentScene = currentProject.sceneList[sceneIndex] + FinderDataManager.instance.type = type + + if (type == FinderDataManager.FragmentType.SPRITE.id) { + textView?.text = createActionBarTitle(2) + } else { + currentSprite = currentScene.spriteList[spriteIndex] + textView?.text = createActionBarTitle(1) + } + + FinderDataManager.instance.currentMatchIndex = brickIndex + + when (type) { + 1 -> activity.onBackPressed() + 2 -> { + projectManager.setCurrentlyEditedScene(currentScene) + activity.onBackPressed() + } + 3 -> { + projectManager.setCurrentSceneAndSprite(currentScene.name, currentSprite.name) + activity.loadFragment(0) + } + 4 -> { + projectManager.setCurrentSceneAndSprite(currentScene.name, currentSprite.name) + activity.loadFragment(1) + } + 5 -> { + projectManager.setCurrentSceneAndSprite(currentScene.name, currentSprite.name) + activity.loadFragment(2) + } + } + + hideKeyboard() + } + }) + + finder?.setOnCloseListener(object : Finder.OnCloseListener { + override fun onClose() { + finishActionMode() + if (!activity.isFinishing) { + activity.setCurrentSceneAndSprite( + projectManager.currentlyEditedScene, + projectManager.currentSprite + ) + activity.supportActionBar?.title = createActionBarTitle(1) + activity.addTabs() + } + activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + } + }) + + finder?.setOnOpenListener(object : Finder.OnOpenListener { + override fun onOpen() { + if (FinderDataManager.instance.getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { + finder.setInitiatingFragment(getFragmentType()) + FinderDataManager.instance.setSearchOrder(getSearchOrder()) + } + activity.removeTabs() + activity.findViewById(R.id.toolbar).visibility = View.GONE + } + }) + } + + fun createActionBarTitle(flag: Int): String { + return if(flag == 1) { + if (currentProject.sceneList != null && currentProject.sceneList.size == 1) { + currentSprite.name + } else { + currentScene.name + ": " + currentSprite.name + } + } else{ + currentScene.name + } + } + + private fun hideKeyboard() { + val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(requireView().windowToken, 0) + } + + protected abstract fun getFragmentType(): FinderDataManager.FragmentType + protected abstract fun getSearchOrder(): Array +} diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/ScriptFinder.kt b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt similarity index 53% rename from catroid/src/main/java/org/catrobat/catroid/ui/ScriptFinder.kt rename to catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt index 37a677186ef..a3fa0398e5e 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/ScriptFinder.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt @@ -49,24 +49,19 @@ import org.koin.java.KoinJavaComponent.inject import java.util.ArrayList import java.util.Locale -class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { +class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { private var onResultFoundListener: OnResultFoundListener? = null private var onCloseListener: OnCloseListener? = null private var onOpenListener: OnOpenListener? = null private val projectManager: ProjectManager by inject(ProjectManager::class.java) - - private var searchResults: MutableList>? = null - private var searchResultIndex = 0 - private var searchQuery = "" - private var binding: ViewScriptFinderBinding - private fun showNavigationButtons() { + fun showNavigationButtons() { + binding.find.visibility = GONE binding.findNext.visibility = VISIBLE binding.findPrevious.visibility = VISIBLE binding.searchPositionIndicator.visibility = VISIBLE - binding.find.visibility = GONE } private fun hideNavigationButtons() { @@ -77,7 +72,7 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } private fun formatSearchQuery(query: CharSequence): String = query.toString().trim() - .toLowerCase(Locale.ROOT) + .lowercase(Locale.ROOT) init { orientation = VERTICAL @@ -93,8 +88,9 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit - override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) { - if (searchQuery == formatSearchQuery(newText)) { + override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: + Int) { + if (FinderDataManager.instance.getSearchQuery() == formatSearchQuery(newText)) { showNavigationButtons() } else { hideNavigationButtons() @@ -114,30 +110,34 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } companion object { - val TAG = ScriptFinder::class.java.simpleName + val TAG = Finder::class.java.simpleName @Suppress("ComplexMethod", "TooGenericExceptionCaught") fun searchBrickViews(v: View?, searchQuery: String): Boolean { try { - if (v is Spinner) { - val selectedItem = v.selectedItem - if (selectedItem is Nameable && selectedItem.name.toLowerCase(Locale.ROOT) - .contains(searchQuery) - ) { - return true + when (v) { + is Spinner -> { + val selectedItem = v.selectedItem + if (selectedItem is Nameable && selectedItem.name.lowercase(Locale.ROOT).contains(searchQuery)) { + FinderDataManager.instance.addtoSearchResultsNames(selectedItem.name.lowercase(Locale.ROOT)) + return true + } } - } else if (v is ViewGroup) { - for (i in 0 until v.childCount) { - val child = v.getChildAt(i) - val queryFoundInBrick = searchBrickViews(child, searchQuery) - if (queryFoundInBrick) { + + is ViewGroup -> { + for (i in 0 until v.childCount) { + val child = v.getChildAt(i) + val queryFoundInBrick = searchBrickViews(child, searchQuery) + if (queryFoundInBrick) return true + } + } + + is TextView -> { + if (v.text.toString().lowercase(Locale.ROOT).contains(searchQuery)) { + FinderDataManager.instance.addtoSearchResultsNames(v.text.toString().lowercase(Locale.ROOT)) return true } } - } else if (v is TextView && v.text.toString().toLowerCase(Locale.ROOT) - .contains(searchQuery) - ) { - return true } } catch (e: NullPointerException) { Log.e(TAG, Log.getStackTraceString(e)) @@ -149,13 +149,14 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex private fun find() { val query = formatSearchQuery(binding.searchBar.text) if (query.isNotEmpty()) { - if (searchQuery != query) { - searchQuery = query + if (FinderDataManager.instance.getSearchQuery() != query) { + FinderDataManager.instance.setSearchQuery(query) + binding.searchBar.setText(query) fillIndices(query) binding.find.visibility = GONE binding.findNext.visibility = VISIBLE binding.findPrevious.visibility = VISIBLE - } else if (searchResults != null) { + } else { findNext() } } else { @@ -167,9 +168,9 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } private fun findNext() { - searchResults?.let { + FinderDataManager.instance.getSearchResults().let { if (it.isNotEmpty()) { - searchResultIndex = (searchResultIndex + 1) % it.size + FinderDataManager.instance.setSearchResultIndex((FinderDataManager.instance.getSearchResultIndex() + 1) % it.size) updateUI() } else { binding.searchPositionIndicator.text = "0/0" @@ -179,10 +180,11 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } private fun findPrevious() { - searchResults?.let { + FinderDataManager.instance.getSearchResults().let { if (it.isNotEmpty()) { - searchResultIndex = - if (searchResultIndex == 0) it.size - 1 else searchResultIndex - 1 + FinderDataManager.instance.setSearchResultIndex(if (FinderDataManager.instance + .getSearchResultIndex() == 0) + it.size - 1 else FinderDataManager.instance.getSearchResultIndex() - 1) updateUI() } else { binding.searchPositionIndicator.text = "0/0" @@ -191,17 +193,26 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } } + fun onFragmentChanged(sceneAndSpriteName:String) { + openForChangeFragment() + + binding.searchPositionIndicator.text = String.format( + Locale.ROOT, "%d/%d", FinderDataManager.instance.getSearchResultIndex() + 1, + FinderDataManager.instance.getSearchResults().size + ) + binding.sceneAndSpriteName.text = sceneAndSpriteName + } private fun updateUI() { - val result = searchResults?.get(searchResultIndex) + val result = FinderDataManager.instance.getSearchResults().get(FinderDataManager.instance.getSearchResultIndex()) binding.searchPositionIndicator.text = String.format( - Locale.ROOT, "%d/%d", searchResultIndex + 1, - searchResults?.size + Locale.ROOT, "%d/%d", FinderDataManager.instance.getSearchResultIndex() + 1, + FinderDataManager.instance.getSearchResults().size ) - result?.let { - searchResults?.size?.let { it1 -> + result.let { + FinderDataManager.instance.getSearchResults().size.let { it1 -> onResultFoundListener?.onResultFound( - it[0], it[1], it[2], it1, + it[0], it[1], it[2],it[3], it1, binding.sceneAndSpriteName ) } @@ -209,19 +220,16 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } fun fillIndices(query: String) { - searchResultIndex = -1 + FinderDataManager.instance.setSearchResultIndex(-1) val activeScene = projectManager.currentlyEditedScene - val activeSprite = projectManager.currentSprite + val activeSprite: Sprite? = projectManager.currentSprite - if (searchResults != null) { - searchResults?.clear() - } else { - searchResults = ArrayList() - } + FinderDataManager.instance.clearSearchResults() + FinderDataManager.instance.clearSearchResultsNames() startThreadToFillIndices(query, activeScene, activeSprite) } - private fun startThreadToFillIndices(query: String, activeScene: Scene, activeSprite: Sprite) { + private fun startThreadToFillIndices(query: String, activeScene: Scene, activeSprite: Sprite?) { Thread { val activity = context as Activity if (!activity.isFinishing) { @@ -233,8 +241,15 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } } val scenes = projectManager.currentProject.sceneList + for (i in scenes.indices) { val scene = scenes[i] + if (FinderDataManager.instance.getInitiatingFragment() == FinderDataManager.FragmentType + .SCENE && scene.name.lowercase(Locale.ROOT).contains(query)){ + FinderDataManager.instance.addtoSearchResults(arrayOf(i, i, i, + FinderDataManager.FragmentType.SCENE.id)) + FinderDataManager.instance.addtoSearchResultsNames(scene.name.lowercase(Locale.ROOT)) + } val spriteList = scene.spriteList for (j in spriteList.indices) { val sprite = spriteList[j] @@ -248,10 +263,42 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex script.setParents() script.addToFlatList(bricks) } - for (k in bricks.indices) { - val brick = bricks[k] - if (searchBrickViews(brick.getView(context), query)) { - searchResults?.add(arrayOf(i, j, k)) + for (order in FinderDataManager.instance.getSearchOrder()){ + when (order) { + 2 -> { + if (sprite.name.lowercase(Locale.ROOT).contains(query)){ + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, j, FinderDataManager.FragmentType.SPRITE.id)) + FinderDataManager.instance.addtoSearchResultsNames(sprite.name.lowercase(Locale.ROOT)) + } + } + 3 -> { + for (k in bricks.indices) { + val brick = bricks[k] + if (searchBrickViews(brick.getView(context), query)) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.SCRIPT.id)) + } + } + } + 4 -> { + val lookList = sprite.lookList + for (k in lookList.indices) { + val look = lookList[k] + if (look.name.lowercase(Locale.ROOT).contains(query)) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.LOOK.id)) + FinderDataManager.instance.addtoSearchResultsNames(look.name.lowercase(Locale.ROOT)) + } + } + } + 5 -> { + val soundList = sprite.soundList + for (k in soundList.indices) { + val sound = soundList[k] + if (sound.name.lowercase(Locale.ROOT).contains(query)) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.SOUND.id)) + FinderDataManager.instance.addtoSearchResultsNames(sound.name.lowercase(Locale.ROOT)) + } + } + } } } } @@ -262,10 +309,12 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex binding.findPrevious.visibility = VISIBLE binding.searchPositionIndicator.visibility = VISIBLE binding.progressBar.visibility = GONE - projectManager.setCurrentSceneAndSprite( - activeScene.name, - activeSprite.name - ) + if (activeSprite != null){ + projectManager.setCurrentSceneAndSprite( + activeScene.name, + activeSprite.name + ) + } findNext() } } @@ -275,25 +324,44 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex val isOpen: Boolean get() = visibility == VISIBLE + fun setInitiatingFragment(fragmentEnum: FinderDataManager.FragmentType){ + FinderDataManager.instance.setInitiatingFragment(fragmentEnum) + } fun open() { this.visibility = VISIBLE - val inputMethodManager = - context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + binding.searchBar.isFocusable + val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.toggleSoftInputFromWindow( - binding.searchBar.applicationWindowToken, - InputMethodManager.SHOW_FORCED, 0 - ) + binding.searchBar.applicationWindowToken, + InputMethodManager.SHOW_FORCED, 0 + ) + onOpenListener?.onOpen() + binding.searchBar.requestFocus() + } + fun disableFocusSearchBar(){ + binding.searchBar.isFocusable = false + } + + private fun openForChangeFragment(){ + this.visibility = VISIBLE + showNavigationButtons() onOpenListener?.onOpen() - binding.searchBar.requestFocus() + binding.searchBar.setText(FinderDataManager.instance.getSearchQuery()) + binding.searchBar.isFocusable = false } fun close() { this.visibility = GONE - searchResults?.clear() - - binding.searchBar.setText("") - searchQuery = "" + FinderDataManager.instance.clearSearchResults() + FinderDataManager.instance.clearSearchResultsNames() + binding.searchBar.text.clear() + binding.searchBar.isFocusableInTouchMode = true + FinderDataManager.instance.setSearchQuery(null) + FinderDataManager.instance.setInitiatingFragment(FinderDataManager.FragmentType.NONE) + FinderDataManager.instance.type = -1 + FinderDataManager.instance.currentMatchIndex = -1 onCloseListener?.onClose() + hideNavigationButtons() this.hideKeyboard() } @@ -317,6 +385,7 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex sceneIndex: Int, spriteIndex: Int, brickIndex: Int, + type: Int, totalResults: Int, textView: TextView? ) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt b/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt new file mode 100644 index 00000000000..88a0e779cae --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt @@ -0,0 +1,102 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2024 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.ui + +import java.util.ArrayList + +class FinderDataManager { + companion object { + val instance:FinderDataManager by lazy { + FinderDataManager() + } + } + enum class FragmentType(val id: Int){ + NONE(0), + SCENE(1), + SPRITE(2), + SCRIPT(3), + LOOK(4), + SOUND(5) + } + + private var initiatingfragment:FragmentType = FragmentType.NONE + private var searchResults = mutableListOf>() + private val searchResultsNames = mutableListOf() + private var searchResultIndex = -1 + private var searchQuery: String? = null + private var searchOrder = arrayOf(-1, -1) + var currentMatchIndex = -1 + var type = -1 + + fun getSearchOrder(): Array{ + return searchOrder + } + + fun setSearchOrder(order: Array){ + searchOrder = order + } + fun setSearchQuery(searchquery: String?){ + searchQuery = searchquery + } + + fun getSearchQuery(): String? { + return searchQuery + } + fun setSearchResultIndex(searchresultIndex:Int){ + searchResultIndex = searchresultIndex + } + + fun getSearchResultIndex(): Int{ + return searchResultIndex + } + fun addtoSearchResults(array: Array){ + searchResults.add(array) + } + fun addtoSearchResultsNames(item: String){ + searchResultsNames.add(item) + } + fun getInitiatingFragment(): FragmentType { + return initiatingfragment + } + + fun setInitiatingFragment(initiatingFragment:FragmentType){ + initiatingfragment = initiatingFragment + } + + fun clearSearchResults(){ + searchResults.clear() + } + + fun getSearchResults(): MutableList> { + return searchResults + } + + fun clearSearchResultsNames(){ + searchResultsNames.clear() + } + + fun getSearchResultsNames(): MutableList { + return searchResultsNames + } +} \ No newline at end of file diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java b/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java index da15cc5ba8f..c3d51c0adbc 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java @@ -289,14 +289,6 @@ public void onBackPressed() { ((ScriptFragment) currentFragment).cancelMove(); return; } - if (((ScriptFragment) currentFragment).isFinderOpen()) { - ((ScriptFragment) currentFragment).closeFinder(); - return; - } - if (((ScriptFragment) currentFragment).isCurrentlyHighlighted()) { - ((ScriptFragment) currentFragment).cancelHighlighting(); - return; - } } else if (currentFragment instanceof FormulaEditorFragment) { ((FormulaEditorFragment) currentFragment).exitFormulaEditorFragment(); return; diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt index eec771f78d9..c4166a2b976 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt @@ -25,6 +25,7 @@ package org.catrobat.catroid.ui.recyclerview.adapter import android.view.View import org.catrobat.catroid.R import org.catrobat.catroid.common.LookData +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder import org.catrobat.catroid.utils.FileMetaDataExtractor import java.util.Locale @@ -34,6 +35,11 @@ class LookAdapter(items: List?) : ExtendedRVAdapter(items) val item = items[position] holder.title.text = item?.name holder.image.setImageBitmap(item?.thumbnailBitmap) + if (position == FinderDataManager.instance.currentMatchIndex) { + holder.itemView.setBackgroundResource(R.drawable.button_background_pressed) + } else { + holder.itemView.setBackgroundResource(R.drawable.button_background_selector) + } if (showDetails) { val measure = item?.measure val measureString = measure?.get(0).toString() + " x " + measure?.get(1) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java index 9808f85ea66..0f3e22a02e4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java @@ -35,6 +35,7 @@ import org.catrobat.catroid.content.GroupItemSprite; import org.catrobat.catroid.content.GroupSprite; import org.catrobat.catroid.content.Sprite; +import org.catrobat.catroid.ui.FinderDataManager; import org.catrobat.catroid.ui.recyclerview.viewholder.CheckableViewHolder; import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder; @@ -102,15 +103,30 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { context.getTheme()); holder.image.setImageDrawable(drawable); holder.checkBox.setVisibility(GONE); + if(isThisFoundObject(position)){ + highlightTheFoundObject(holder); + } + else{ + cancelHighlightTheFoundObject(holder); + } return; } - if (holder.getItemViewType() == BACKGROUND) { + else if (holder.getItemViewType() == BACKGROUND) { holder.itemView.setOnLongClickListener(null); holder.checkBox.setVisibility(GONE); + if (isThisFoundObject(position)) { + View viewBackgroundButton = + holder.itemView.findViewById(R.id.view_holder_background); + viewBackgroundButton.setBackgroundResource(R.drawable.button_background_pressed); + } + else{ + View viewBackgroundButton = holder.itemView.findViewById(R.id.view_holder_background); + viewBackgroundButton.setBackgroundResource(R.drawable.button_background_selector); + } } - if (holder.getItemViewType() == SPRITE_GROUP_ITEM) { + else if (holder.getItemViewType() == SPRITE_GROUP_ITEM) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams .MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); holder.itemView.setLayoutParams(params); @@ -118,6 +134,21 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { params.height = 0; holder.itemView.setLayoutParams(params); } + if(isThisFoundObject(position)){ + highlightTheFoundObject(holder); + } + else{ + cancelHighlightTheFoundObject(holder); + } + } + + else{ + if(isThisFoundObject(position)){ + highlightTheFoundObject(holder); + } + else{ + cancelHighlightTheFoundObject(holder); + } } Bitmap lookData = null; @@ -126,6 +157,7 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { } holder.image.setImageBitmap(lookData); + if (showDetails) { holder.details.setText(String.format(Locale.getDefault(), context.getString(R.string.sprite_details), @@ -137,7 +169,15 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { holder.details.setVisibility(GONE); } } - + private boolean isThisFoundObject(int position){ + return position == FinderDataManager.Companion.getInstance().getCurrentMatchIndex(); + } + private void cancelHighlightTheFoundObject(ExtendedViewHolder holder){ + holder.itemView.setBackgroundResource(R.drawable.button_background_selector); + } + private void highlightTheFoundObject(ExtendedViewHolder holder){ + holder.itemView.setBackgroundResource(R.drawable.button_background_pressed); + } @Override public @ViewType int getItemViewType(int position) { if (position == 0) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java index 0c73bc1d912..c436958796c 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java @@ -23,6 +23,7 @@ package org.catrobat.catroid.ui.recyclerview.adapter; +import android.graphics.Color; import android.view.View; import org.catrobat.catroid.ProjectManager; @@ -30,12 +31,15 @@ import org.catrobat.catroid.content.Scene; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.io.ProjectAndSceneScreenshotLoader; +import org.catrobat.catroid.ui.FinderDataManager; import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder; import java.io.File; import java.util.List; import java.util.Locale; +import static android.view.View.GONE; + public class SceneAdapter extends ExtendedRVAdapter { public SceneAdapter(List items) { @@ -54,6 +58,12 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { loader.loadAndShowScreenshot(projectDir.getName(), item.getDirectory().getName(), false, holder.image); + if (position == FinderDataManager.Companion.getInstance().getCurrentMatchIndex()) { + holder.itemView.setBackgroundResource(R.drawable.button_background_pressed); + } else { + holder.itemView.setBackgroundResource(R.drawable.button_background_selector); + } + if (showDetails) { holder.details.setText(String.format(Locale.getDefault(), holder.itemView.getContext().getString(R.string.scene_details), diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt index 32fb683067a..0f438463748 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt @@ -28,6 +28,7 @@ import android.text.format.DateUtils import android.util.Log import org.catrobat.catroid.R import org.catrobat.catroid.common.SoundInfo +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder import org.catrobat.catroid.utils.FileMetaDataExtractor import java.io.IOException @@ -47,6 +48,12 @@ class SoundAdapter(items: List?) : ExtendedRVAdapter(ite holder?.title?.text = item?.name holder?.image?.setImageResource(R.drawable.ic_media_play_dark) + if (position == FinderDataManager.instance.currentMatchIndex) { + holder?.itemView?.setBackgroundResource(R.drawable.button_background_pressed) + } else { + holder?.itemView?.setBackgroundResource(R.drawable.button_background_selector) + } + holder?.image?.setOnClickListener { if (mediaPlayer.isPlaying) { holder.image.setImageResource(R.drawable.ic_media_play_dark) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java index 271733da3bf..3b1a103ffd9 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java @@ -31,6 +31,7 @@ import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder; + import java.util.List; import java.util.Locale; diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt index e347551b89a..c0a57d65767 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt @@ -36,6 +36,8 @@ import org.catrobat.catroid.common.Constants import org.catrobat.catroid.common.LookData import org.catrobat.catroid.common.SharedPreferenceKeys.SHOW_DETAILS_LOOKS_PREFERENCE_KEY import org.catrobat.catroid.io.StorageOperations +import org.catrobat.catroid.ui.BaseFinderFragment +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.SpriteActivity import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.controller.BackpackListManager @@ -49,17 +51,23 @@ import org.koin.android.ext.android.inject import java.io.IOException import java.util.ArrayList -class LookListFragment : RecyclerViewFragment() { +class LookListFragment : BaseFinderFragment() { private val lookController = LookController() private var currentItem: LookData? = null - private val projectManager: ProjectManager by inject() - companion object { @JvmField val TAG = LookListFragment::class.java.simpleName } + override fun getFragmentType(): FinderDataManager.FragmentType { + return FinderDataManager.FragmentType.LOOK + } + + override fun getSearchOrder(): Array { + return arrayOf(4, 5, 3) + } + override fun initializeAdapter() { sharedPreferenceDetailsKey = SHOW_DETAILS_LOOKS_PREFERENCE_KEY val items = projectManager.currentSprite.lookList @@ -72,7 +80,7 @@ class LookListFragment : RecyclerViewFragment() { super.onPrepareOptionsMenu(menu) menu.findItem(R.id.catblocks_reorder_scripts).isVisible = false menu.findItem(R.id.catblocks).isVisible = false - menu.findItem(R.id.find).isVisible = false + menu.findItem(R.id.find).isVisible = true } override fun onResume() { @@ -253,6 +261,7 @@ class LookListFragment : RecyclerViewFragment() { R.id.project_options, R.id.edit, R.id.from_local, + R.id.find ) val popupMenu = UiUtils.createSettingsPopUpMenu(view, requireContext(), R.menu .menu_project_activity, hiddenOptionMenuIds) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java index d1a72a6942c..b8da482d67a 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java @@ -39,6 +39,8 @@ import org.catrobat.catroid.common.Nameable; import org.catrobat.catroid.merge.NewProjectNameTextWatcher; import org.catrobat.catroid.ui.BottomBar; +import org.catrobat.catroid.ui.Finder; +import org.catrobat.catroid.ui.SpriteActivity; import org.catrobat.catroid.ui.controller.BackpackListManager; import org.catrobat.catroid.ui.recyclerview.adapter.ExtendedRVAdapter; import org.catrobat.catroid.ui.recyclerview.adapter.MultiViewSpriteAdapter; @@ -50,6 +52,7 @@ import org.catrobat.catroid.ui.recyclerview.util.UniqueNameProvider; import org.catrobat.catroid.ui.recyclerview.viewholder.CheckableViewHolder; import org.catrobat.catroid.utils.ToastUtil; +import org.catrobat.catroid.ui.FinderDataManager; import org.jetbrains.annotations.NotNull; import java.lang.annotation.Retention; @@ -88,6 +91,9 @@ public abstract class RecyclerViewFragment extends Fragment protected View parentView; protected RecyclerView recyclerView; + protected Finder finder; + protected SpriteActivity activity; + protected TextView emptyView; protected ExtendedRVAdapter adapter; @@ -239,6 +245,7 @@ protected void resetActionModeParameters() { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { parentView = inflater.inflate(R.layout.fragment_list_view, container, false); + finder = parentView.findViewById(R.id.findview); recyclerView = parentView.findViewById(R.id.recycler_view); emptyView = parentView.findViewById(R.id.empty_view); setShowProgressBar(true); @@ -349,6 +356,9 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.merge: startActionMode(MERGE); break; + case R.id.find: + finder.open(); + break; case R.id.show_details: adapter.showDetails = !adapter.showDetails; PreferenceManager.getDefaultSharedPreferences(getActivity()) @@ -580,4 +590,20 @@ protected void mergeProjects(List selectedProjects, String mergeProjectName) ToastUtil.showSuccess(getContext(), R.string.merging_project_text); finishActionMode(); } + + protected void scrollToSearchResult() { + int indexSearch = FinderDataManager.Companion.getInstance().getSearchResultIndex(); + List searchResults = + FinderDataManager.Companion.getInstance().getSearchResults(); + + if (searchResults != null && indexSearch < searchResults.size()) { + Integer[] result = searchResults.get(indexSearch); + if (result != null && result.length > 2) { + Integer value = result[2]; + if (value != null) { + recyclerView.scrollToPosition(value); + } + } + } + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt index 50a2fe889ef..880b52a342a 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt @@ -22,21 +22,32 @@ */ package org.catrobat.catroid.ui.recyclerview.fragment +import android.content.Context import android.content.Intent import android.util.Log import android.view.Menu +import android.os.Bundle import android.view.View import androidx.annotation.PluralsRes import androidx.appcompat.app.AppCompatActivity import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R import org.catrobat.catroid.common.Constants +import android.view.LayoutInflater +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.TextView + import org.catrobat.catroid.common.SharedPreferenceKeys +import org.catrobat.catroid.content.Project import org.catrobat.catroid.content.Scene import org.catrobat.catroid.content.Sprite import org.catrobat.catroid.io.XstreamSerializer import org.catrobat.catroid.io.asynctask.ProjectLoader.ProjectLoadListener import org.catrobat.catroid.io.asynctask.loadProject +import org.catrobat.catroid.ui.FinderDataManager +import org.catrobat.catroid.ui.ProjectActivity +import org.catrobat.catroid.ui.Finder import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.controller.BackpackListManager import org.catrobat.catroid.ui.recyclerview.adapter.SceneAdapter @@ -53,8 +64,70 @@ class SceneListFragment : RecyclerViewFragment(), private val sceneController = SceneController() private val projectManager: ProjectManager by inject() + private lateinit var currentProject: Project + private lateinit var currentScene: Scene + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val parentView = super.onCreateView(inflater, container, savedInstanceState) + val activity = getActivity() as ProjectActivity + recyclerView = parentView!!.findViewById(R.id.recycler_view) + currentProject = ProjectManager.getInstance().currentProject + currentScene = ProjectManager.getInstance().currentlyEditedScene + + finder?.setOnResultFoundListener(object : Finder.OnResultFoundListener { + override fun onResultFound( + sceneIndex: Int, + spriteIndex: Int, + brickIndex: Int, + type: Int, + totalResults: Int, + textView: TextView? + ) { + + currentScene = currentProject.sceneList[sceneIndex] + FinderDataManager.instance.type = type + FinderDataManager.instance.currentMatchIndex = brickIndex + + if (type != FinderDataManager.FragmentType.SCENE.id) { + onItemClick(currentScene,MultiSelectionManager()) + } else { + textView?.text = createActionBarTitle() + initializeAdapter() + adapter.notifyDataSetChanged() + scrollToSearchResult() + finder.disableFocusSearchBar() + } + hideKeyboard() + } + }) + finder?.setOnCloseListener(object : Finder.OnCloseListener { + override fun onClose() { + activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + finishActionMode() + } + }) + + finder?.setOnOpenListener(object : Finder.OnOpenListener { + override fun onOpen() { + activity.findViewById(R.id.toolbar).visibility = View.GONE + finder.setInitiatingFragment(FinderDataManager.FragmentType.SCENE) + val order = arrayOf(2, 3, 4, 5) + FinderDataManager.instance.setSearchOrder(order) + } + }) + + return parentView + } + fun createActionBarTitle(): String { + return currentProject.name + } + private fun hideKeyboard() { + val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(requireView().windowToken, 0) + } override fun onResume() { super.onResume() + val currentProject = projectManager.currentProject if (currentProject.sceneList.size < 2) { projectManager.currentlyEditedScene = currentProject.defaultScene @@ -62,8 +135,17 @@ class SceneListFragment : RecyclerViewFragment(), } projectManager.currentlyEditedScene = currentProject.defaultScene (requireActivity() as AppCompatActivity).supportActionBar?.title = currentProject.name - } + if (FinderDataManager.instance.getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + val sceneAndSpriteName = createActionBarTitle() + finder.onFragmentChanged(sceneAndSpriteName) + scrollToSearchResult() + hideKeyboard() + } + else{ + finder.close() + } + } private fun switchToSpriteListFragment() { parentFragmentManager.beginTransaction() .replace(R.id.fragment_container, SpriteListFragment(), SpriteListFragment.TAG) @@ -232,6 +314,7 @@ class SceneListFragment : RecyclerViewFragment(), R.id.project_options, R.id.edit, R.id.from_local, + R.id.find ) val popupMenu = UiUtils.createSettingsPopUpMenu(view, requireContext(), R.menu .menu_project_activity, hiddenOptionMenuIds) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index 202d3c0403e..28f14a90730 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -40,6 +40,7 @@ import android.widget.ListAdapter; import org.catrobat.catroid.BuildConfig; + import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; import org.catrobat.catroid.common.ScreenValues; @@ -64,8 +65,10 @@ import org.catrobat.catroid.io.asynctask.ProjectLoader; import org.catrobat.catroid.io.asynctask.ProjectSaver; import org.catrobat.catroid.ui.BottomBar; -import org.catrobat.catroid.ui.ScriptFinder; +import org.catrobat.catroid.ui.FinderDataManager; +import org.catrobat.catroid.ui.Finder; import org.catrobat.catroid.ui.SpriteActivity; +import org.catrobat.catroid.ui.SpriteActivityOnTabSelectedListenerKt; import org.catrobat.catroid.ui.UiUtils; import org.catrobat.catroid.ui.controller.BackpackListManager; import org.catrobat.catroid.ui.controller.RecentBrickListManager; @@ -137,7 +140,7 @@ public class ScriptFragment extends ListFragment implements private ActionMode actionMode; private BrickAdapter adapter; private BrickListView listView; - private ScriptFinder scriptFinder; + private Finder finder; private String currentSceneName; private String currentSpriteName; private int undoBrickPosition; @@ -274,7 +277,6 @@ private void resetActionModeParameters() { actionMode = null; adapter.setCheckBoxMode(BrickAdapter.NONE); } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = View.inflate(getActivity(), R.layout.fragment_script, null); @@ -291,29 +293,58 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa activity = (SpriteActivity) getActivity(); SettingsFragment.setToChosenLanguage(activity); - scriptFinder = view.findViewById(R.id.findview); - scriptFinder.setOnResultFoundListener((sceneIndex, spriteIndex, brickIndex, totalResults, + finder = view.findViewById(R.id.findview); + finder.setOnResultFoundListener((sceneIndex, spriteIndex, brickIndex,type, + totalResults, textView ) -> { Project currentProject = ProjectManager.getInstance().getCurrentProject(); Scene currentScene = currentProject.getSceneList().get(sceneIndex); - Sprite currentSprite = currentScene.getSpriteList().get(spriteIndex); - - textView.setText(createActionBarTitle(currentProject, - currentScene, - currentSprite)); + Sprite currentSprite = null; + if(type != FinderDataManager.FragmentType.SCENE.getId()){ + currentSprite = currentScene.getSpriteList().get(spriteIndex); + ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), currentSprite.getName()); + } + FinderDataManager.Companion.getInstance().setType(type); - ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), - currentSprite.getName()); + if(type != FinderDataManager.FragmentType.SPRITE.getId() && type != FinderDataManager.FragmentType.SCENE.getId()) { + textView.setText(createActionBarTitle(currentProject, currentScene, currentSprite,1)); + } + else{ + textView.setText(createActionBarTitle(currentProject, currentScene, currentSprite,2)); + } - adapter.updateItems(currentSprite); - adapter.notifyDataSetChanged(); - listView.smoothScrollToPosition(brickIndex); - highlightBrickAtIndex(brickIndex); - hideKeyboard(); + FinderDataManager.Companion.getInstance().setCurrentMatchIndex(brickIndex); + + if(type != FinderDataManager.FragmentType.SCRIPT.getId()){ + switch (type){ + case 1: + activity.onBackPressed(); + break; + case 2: + ProjectManager.getInstance().setCurrentlyEditedScene(currentScene); + activity.onBackPressed(); + break; + case 4: + SpriteActivityOnTabSelectedListenerKt.loadFragment(activity,1); + ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), currentSprite.getName()); + break; + case 5: + SpriteActivityOnTabSelectedListenerKt.loadFragment(activity,2); + ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), currentSprite.getName()); + break; + } + } + else{ + adapter.updateItems(currentSprite); + adapter.notifyDataSetChanged(); + listView.smoothScrollToPosition(brickIndex); + highlightBrickAtIndex(brickIndex); + hideKeyboard(); + } }); - scriptFinder.setOnCloseListener(() -> { + finder.setOnCloseListener(() -> { listView.cancelHighlighting(); finishActionMode(); if (activity != null && !activity.isFinishing()) { @@ -325,20 +356,43 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa activity.findViewById(R.id.toolbar).setVisibility(View.VISIBLE); }); - scriptFinder.setOnOpenListener(() -> { + finder.setOnOpenListener(() -> { + if (FinderDataManager.Companion.getInstance().getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { + finder.setInitiatingFragment(FinderDataManager.FragmentType.SCRIPT); + Integer[] order = {3, 4, 5}; + FinderDataManager.Companion.getInstance().setSearchOrder(order); + } activity.removeTabs(); activity.findViewById(R.id.toolbar).setVisibility(View.GONE); }); + if (FinderDataManager.Companion.getInstance().getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + String sceneAndSpriteName = + createActionBarTitle(ProjectManager.getInstance().getCurrentProject(), + ProjectManager.getInstance().getStartScene(), + ProjectManager.getInstance().getCurrentSprite(),1); + finder.onFragmentChanged(sceneAndSpriteName); + int indexSearch = FinderDataManager.Companion.getInstance().getSearchResultIndex(); + int brickIndex = FinderDataManager.Companion.getInstance().getSearchResults().get(indexSearch)[2]; + listView.smoothScrollToPosition(brickIndex); + highlightBrickAtIndex(brickIndex); + } + setHasOptionsMenu(true); return view; } - public String createActionBarTitle(Project currentProject, Scene currentScene, Sprite currentSprite) { - if (currentProject.getSceneList().size() == 1) { - return currentSprite.getName(); - } else { - return currentScene.getName() + ": " + currentSprite.getName(); + public String createActionBarTitle(Project currentProject, Scene currentScene, + Sprite currentSprite, int flag) { + if(flag == 1) { + if (currentProject.getSceneList().size() == 1) { + return currentSprite.getName(); + } else { + return currentScene.getName() + ": " + currentSprite.getName(); + } + } + else{ + return currentScene.getName(); } } @@ -356,7 +410,7 @@ private void hideKeyboard() { @Override public void onDestroyView() { super.onDestroyView(); - if (scriptFinder.isOpen() && activity != null) { + if (finder.isOpen() && activity != null) { activity.findViewById(R.id.toolbar).setVisibility(View.VISIBLE); } } @@ -477,7 +531,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switchToCatblocks(); break; case R.id.find: - scriptFinder.open(); + finder.open(); break; default: return super.onOptionsItemSelected(item); @@ -1096,12 +1150,12 @@ public int getActionModeType() { } public boolean isFinderOpen() { - return scriptFinder.isOpen(); + return finder.isOpen(); } public void closeFinder() { - if (!scriptFinder.isClosed()) { - scriptFinder.close(); + if (!finder.isClosed()) { + finder.close(); } } } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt index 4b9779a48ee..6f6eda4f68a 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt @@ -28,11 +28,12 @@ import android.view.Menu import android.view.View import androidx.annotation.PluralsRes import org.catrobat.catroid.BuildConfig -import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R import org.catrobat.catroid.common.SharedPreferenceKeys import org.catrobat.catroid.common.SoundInfo import org.catrobat.catroid.pocketmusic.PocketMusicActivity +import org.catrobat.catroid.ui.BaseFinderFragment +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.controller.BackpackListManager import org.catrobat.catroid.ui.recyclerview.adapter.SoundAdapter @@ -41,19 +42,26 @@ import org.catrobat.catroid.ui.recyclerview.backpack.BackpackActivity import org.catrobat.catroid.ui.recyclerview.controller.SoundController import org.catrobat.catroid.utils.SnackbarUtil import org.catrobat.catroid.utils.ToastUtil -import org.koin.android.ext.android.inject import java.io.IOException -class SoundListFragment : RecyclerViewFragment() { +class SoundListFragment : BaseFinderFragment() { private val soundController = SoundController() - private val projectManager: ProjectManager by inject() + companion object { @JvmField val TAG = SoundListFragment::class.java.simpleName } + override fun getFragmentType(): FinderDataManager.FragmentType { + return FinderDataManager.FragmentType.LOOK + } + + override fun getSearchOrder(): Array { + return arrayOf(4, 5, 3) + } + override fun initializeAdapter() { sharedPreferenceDetailsKey = SharedPreferenceKeys.SHOW_DETAILS_SOUNDS_PREFERENCE_KEY val items = projectManager.currentSprite.soundList @@ -77,7 +85,7 @@ class SoundListFragment : RecyclerViewFragment() { menu.findItem(R.id.catblocks_reorder_scripts).isVisible = false menu.findItem(R.id.catblocks).isVisible = false - menu.findItem(R.id.find).isVisible = false + menu.findItem(R.id.find).isVisible = true } override fun packItems(selectedItems: List) { @@ -205,6 +213,7 @@ class SoundListFragment : RecyclerViewFragment() { R.id.project_options, R.id.edit, R.id.from_local, + R.id.find ) val popupMenu = UiUtils.createSettingsPopUpMenu(view, requireContext(), R.menu .menu_project_activity, hiddenOptionMenuIds) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt index ccb492c7819..9194cb699fa 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt @@ -24,14 +24,20 @@ package org.catrobat.catroid.ui.recyclerview.fragment import android.annotation.SuppressLint import android.app.Activity +import android.content.Context import android.content.DialogInterface import android.content.Intent import android.net.Uri +import android.os.Bundle import android.preference.PreferenceManager import android.util.Log +import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.TextView import androidx.annotation.PluralsRes import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.ItemTouchHelper @@ -41,13 +47,19 @@ import org.catrobat.catroid.R import org.catrobat.catroid.common.Constants import org.catrobat.catroid.common.Constants.TMP_IMAGE_FILE_NAME import org.catrobat.catroid.common.SharedPreferenceKeys +import org.catrobat.catroid.content.GroupItemSprite import org.catrobat.catroid.content.GroupSprite +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene import org.catrobat.catroid.content.Sprite import org.catrobat.catroid.io.StorageOperations import org.catrobat.catroid.merge.ImportProjectHelper +import org.catrobat.catroid.ui.FinderDataManager +import org.catrobat.catroid.ui.ProjectActivity import org.catrobat.catroid.ui.ProjectListActivity import org.catrobat.catroid.ui.ProjectListActivity.Companion.IMPORT_LOCAL_INTENT import org.catrobat.catroid.ui.SpriteActivity +import org.catrobat.catroid.ui.Finder import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.WebViewActivity import org.catrobat.catroid.ui.controller.BackpackListManager @@ -73,6 +85,8 @@ class SpriteListFragment : RecyclerViewFragment() { private val projectManager: ProjectManager by inject() private var currentSprite: Sprite? = null + private lateinit var currentProject: Project + private lateinit var currentScene: Scene internal inner class MultiViewTouchHelperCallback(adapterInterface: TouchHelperAdapterInterface?) : TouchHelperCallback(adapterInterface) { @@ -105,10 +119,115 @@ class SpriteListFragment : RecyclerViewFragment() { public override fun shouldShowEmptyView() = adapter.itemCount == 1 override fun onResume() { + currentScene = ProjectManager.getInstance().currentlyEditedScene + initializeAdapter() + super.onResume() SnackbarUtil.showHintSnackbar(requireActivity(), R.string.hint_objects) - val currentProject = projectManager.currentProject + makeTitle() + + if (FinderDataManager.instance.getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + handleFinderDataManagerLogic() + if (FinderDataManager.instance.type != FinderDataManager.FragmentType.SCENE.id){ + unCollapseFoundObject(FinderDataManager.instance.currentMatchIndex) + } + } + else{ + finder.close() + } + } + + private fun handleFinderDataManagerLogic() { + val activity = getActivity() as ProjectActivity + + if(FinderDataManager.instance.type == FinderDataManager.FragmentType.SCENE.id){ + activity.onBackPressed() + } + else{ + val searchIndex = FinderDataManager.instance.getSearchResultIndex() + val spriteIndex = FinderDataManager.instance.getSearchResults()[searchIndex][1] + projectManager.currentSprite = currentScene.spriteList[spriteIndex] + + when (FinderDataManager.instance.type) { + FinderDataManager.FragmentType.SCENE.id -> activity.onBackPressed() + else -> startActivity(createSpriteActivityIntent(FinderDataManager.instance.type)) + } + } + val sceneAndSpriteName = createActionBarTitle() + finder.onFragmentChanged(sceneAndSpriteName) + scrollToSearchResult() + hideKeyboard() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val parentView = super.onCreateView(inflater, container, savedInstanceState) + recyclerView = parentView!!.findViewById(R.id.recycler_view) + currentProject = ProjectManager.getInstance().currentProject + currentScene = ProjectManager.getInstance().currentlyEditedScene + val activity = getActivity() as ProjectActivity + + finder?.setOnResultFoundListener(object : Finder.OnResultFoundListener { + override fun onResultFound( + sceneIndex: Int, + spriteIndex: Int, + brickIndex: Int, + type: Int, + totalResults: Int, + textView: TextView? + ) { + + currentProject = ProjectManager.getInstance().currentProject + currentScene = currentProject.sceneList[sceneIndex] + ProjectManager.getInstance().setCurrentlyEditedScene(currentScene) + + makeTitle() + + FinderDataManager.instance.currentMatchIndex = brickIndex + + when (type) { + FinderDataManager.FragmentType.SPRITE.id -> { + textView?.text = createActionBarTitle() + initializeAdapter() + unCollapseFoundObject(spriteIndex) + adapter.notifyDataSetChanged() + scrollToSearchResult() + finder.disableFocusSearchBar() + + } + FinderDataManager.FragmentType.SCENE.id -> { + activity.onBackPressed() + } + else -> { + projectManager.currentSprite = currentProject.sceneList[sceneIndex].spriteList[spriteIndex] + val intent = createSpriteActivityIntent(type) + startActivity(intent) + } + } + hideKeyboard() + } + }) + + finder?.setOnCloseListener(object : Finder.OnCloseListener { + override fun onClose() { + finishActionMode() + activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + } + }) + + finder?.setOnOpenListener(object : Finder.OnOpenListener { + override fun onOpen() { + activity.findViewById(R.id.toolbar).visibility = View.GONE + finder.setInitiatingFragment(FinderDataManager.FragmentType.SPRITE) + val order = arrayOf(2,3,4,5) + FinderDataManager.instance.setSearchOrder(order) + } + }) + return parentView + } + + private fun makeTitle(){ + currentProject = ProjectManager.getInstance().currentProject val title: String = if (currentProject.sceneList.size < 2) { currentProject.name } else { @@ -120,6 +239,40 @@ class SpriteListFragment : RecyclerViewFragment() { (requireActivity() as AppCompatActivity).supportActionBar?.title = title } + private fun unCollapseFoundObject(spriteIndex: Int) { + + val currentItem = currentScene.spriteList[spriteIndex] + if (currentItem is GroupItemSprite && currentItem.isCollapsed){ + for (i in spriteIndex downTo 1) { + val groupItem = currentScene.spriteList[i] + if (groupItem is GroupSprite) { + groupItem.isCollapsed = false + break + } + } + } + } + + private fun createSpriteActivityIntent(type: Int): Intent { + val intent = Intent(requireContext(), SpriteActivity::class.java) + intent.putExtra( + SpriteActivity.EXTRA_FRAGMENT_POSITION, + when (type) { + FinderDataManager.FragmentType.SOUND.id -> SpriteActivity.FRAGMENT_SOUNDS + FinderDataManager.FragmentType.LOOK.id -> SpriteActivity.FRAGMENT_LOOKS + else -> SpriteActivity.FRAGMENT_SCRIPTS + } + ) + return intent + } + + fun createActionBarTitle(): String { + return currentScene.name + } + private fun hideKeyboard() { + val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(requireView().windowToken, 0) + } override fun onAdapterReady() { super.onAdapterReady() val callback: ItemTouchHelper.Callback = MultiViewTouchHelperCallback(adapter) @@ -130,6 +283,7 @@ class SpriteListFragment : RecyclerViewFragment() { override fun onPrepareOptionsMenu(menu: Menu) { super.onPrepareOptionsMenu(menu) menu.findItem(R.id.new_group).isVisible = true + menu.findItem(R.id.find).isVisible = true } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -142,8 +296,8 @@ class SpriteListFragment : RecyclerViewFragment() { } private fun handleSelectedOptionItem(item: MenuItem) { - if (adapter.items.size == 1) { - ToastUtil.showError(activity, R.string.am_empty_list) + if (adapter.items.size == 1 && item.title.toString() != "Search") { + ToastUtil.showError(getActivity(), R.string.am_empty_list) resetActionModeParameters() } else { super.onOptionsItemSelected(item) @@ -321,6 +475,9 @@ class SpriteListFragment : RecyclerViewFragment() { } override fun onItemClick(item: Sprite?, selectionManager: MultiSelectionManager?) { + if (finder.isOpen){ + finder.close() + } if (item is GroupSprite) { item.isCollapsed = !item.isCollapsed adapter.notifyDataSetChanged() @@ -352,7 +509,8 @@ class SpriteListFragment : RecyclerViewFragment() { val itemList = mutableListOf() itemList.add(item) val hiddenMenuOptionIds = mutableListOf( - R.id.new_group, R.id.project_options, R.id.new_scene, R.id.show_details, R.id.edit + R.id.new_group, R.id.project_options, R.id.new_scene, R.id.show_details, R.id.edit,R + .id.find ) if (item is GroupSprite) { hiddenMenuOptionIds.add(R.id.backpack) diff --git a/catroid/src/main/res/layout/fragment_list_view.xml b/catroid/src/main/res/layout/fragment_list_view.xml index 0cf9180b67f..a073205b61f 100644 --- a/catroid/src/main/res/layout/fragment_list_view.xml +++ b/catroid/src/main/res/layout/fragment_list_view.xml @@ -1,4 +1,3 @@ - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:visibility="gone"/> - - + android:layout_height="0dp" + android:layout_weight="1"> + + + + + + + - + diff --git a/catroid/src/main/res/layout/fragment_script.xml b/catroid/src/main/res/layout/fragment_script.xml index 7e4177c59b5..7db7aebc0f4 100644 --- a/catroid/src/main/res/layout/fragment_script.xml +++ b/catroid/src/main/res/layout/fragment_script.xml @@ -28,7 +28,7 @@ android:layout_weight="1" android:orientation="vertical" > - - + + + Date: Sun, 14 Sep 2025 16:33:02 +0200 Subject: [PATCH 2/5] Review corrections --- catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt | 3 +-- .../catroid/ui/recyclerview/fragment/LookListFragment.kt | 2 +- .../catroid/ui/recyclerview/fragment/ScriptFragment.java | 2 +- .../catroid/ui/recyclerview/fragment/SoundListFragment.kt | 2 +- .../catroid/ui/recyclerview/fragment/SpriteListFragment.kt | 1 + 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt index a3fa0398e5e..0325e7c531f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt @@ -244,8 +244,7 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att for (i in scenes.indices) { val scene = scenes[i] - if (FinderDataManager.instance.getInitiatingFragment() == FinderDataManager.FragmentType - .SCENE && scene.name.lowercase(Locale.ROOT).contains(query)){ + if (scene.name.lowercase(Locale.ROOT).contains(query)){ FinderDataManager.instance.addtoSearchResults(arrayOf(i, i, i, FinderDataManager.FragmentType.SCENE.id)) FinderDataManager.instance.addtoSearchResultsNames(scene.name.lowercase(Locale.ROOT)) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt index c0a57d65767..a5736e99882 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt @@ -65,7 +65,7 @@ class LookListFragment : BaseFinderFragment() { } override fun getSearchOrder(): Array { - return arrayOf(4, 5, 3) + return arrayOf(2, 4, 5, 3) } override fun initializeAdapter() { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index 28f14a90730..63cc5b74b80 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -359,7 +359,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa finder.setOnOpenListener(() -> { if (FinderDataManager.Companion.getInstance().getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { finder.setInitiatingFragment(FinderDataManager.FragmentType.SCRIPT); - Integer[] order = {3, 4, 5}; + Integer[] order = {2, 3, 4, 5}; FinderDataManager.Companion.getInstance().setSearchOrder(order); } activity.removeTabs(); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt index 6f6eda4f68a..89a8be024c4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt @@ -59,7 +59,7 @@ class SoundListFragment : BaseFinderFragment() { } override fun getSearchOrder(): Array { - return arrayOf(4, 5, 3) + return arrayOf(2, 4, 5, 3) } override fun initializeAdapter() { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt index 9194cb699fa..13bf85a4ca9 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt @@ -151,6 +151,7 @@ class SpriteListFragment : RecyclerViewFragment() { when (FinderDataManager.instance.type) { FinderDataManager.FragmentType.SCENE.id -> activity.onBackPressed() + FinderDataManager.FragmentType.SPRITE.id -> {} else -> startActivity(createSpriteActivityIntent(FinderDataManager.instance.type)) } } From b5705aeead8df54a9a3e0bddc9af8a48c04c3c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tine=20Podlun=C5=A1ek?= Date: Wed, 25 Sep 2024 14:47:06 +0200 Subject: [PATCH 3/5] Extended search feature to names of scenes, groups, objects, looks, and sounds --- .../catrobat/catroid/test/ui/SearchTest.kt | 210 ++++++++++++++++++ .../catrobat/catroid/ui/BaseFinderFragment.kt | 161 ++++++++++++++ .../catroid/ui/{ScriptFinder.kt => Finder.kt} | 202 +++++++++++------ .../catrobat/catroid/ui/FinderDataManager.kt | 102 +++++++++ .../catrobat/catroid/ui/SpriteActivity.java | 8 - .../ui/recyclerview/adapter/LookAdapter.kt | 6 + .../adapter/MultiViewSpriteAdapter.java | 46 +++- .../ui/recyclerview/adapter/SceneAdapter.java | 10 + .../ui/recyclerview/adapter/SoundAdapter.kt | 7 + .../recyclerview/adapter/SpriteAdapter.java | 1 + .../recyclerview/fragment/LookListFragment.kt | 17 +- .../fragment/RecyclerViewFragment.java | 26 +++ .../fragment/SceneListFragment.kt | 85 ++++++- .../recyclerview/fragment/ScriptFragment.java | 112 +++++++--- .../fragment/SoundListFragment.kt | 19 +- .../fragment/SpriteListFragment.kt | 167 +++++++++++++- .../main/res/layout/fragment_list_view.xml | 50 +++-- .../src/main/res/layout/fragment_script.xml | 2 +- .../layout/view_holder_background_sprite.xml | 6 +- .../main/res/menu/menu_project_activity.xml | 5 + 20 files changed, 1100 insertions(+), 142 deletions(-) create mode 100644 catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt create mode 100644 catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt rename catroid/src/main/java/org/catrobat/catroid/ui/{ScriptFinder.kt => Finder.kt} (53%) create mode 100644 catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt diff --git a/catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt b/catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt new file mode 100644 index 00000000000..fea2558bc5e --- /dev/null +++ b/catroid/src/androidTest/java/org/catrobat/catroid/test/ui/SearchTest.kt @@ -0,0 +1,210 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2025 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.test.ui +import android.view.KeyEvent +import androidx.recyclerview.widget.RecyclerView +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.Espresso +import androidx.test.espresso.action.ViewActions +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.contrib.RecyclerViewActions +import androidx.test.espresso.matcher.ViewMatchers.assertThat +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import org.catrobat.catroid.ProjectManager +import org.catrobat.catroid.R +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.ui.FinderDataManager +import org.catrobat.catroid.ui.MainMenuActivity +import org.catrobat.catroid.uiespresso.ui.fragment.actionutils.ActionUtils +import org.hamcrest.Matchers.`is` +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.catrobat.catroid.content.Script +import org.catrobat.catroid.content.StartScript +import org.catrobat.catroid.content.bricks.FinishStageBrick + +@RunWith(AndroidJUnit4::class) +class SearchTest { + var projectName = "searchTestProject" + private val projectManager = ProjectManager.getInstance() + + @Rule + @JvmField + var baseActivityTestRule = ActivityScenarioRule(MainMenuActivity::class.java) + private lateinit var script: Script + + @Before + fun setUp() { + createProject(projectName) + } + + @Test + fun testSearchMixed() { + val queryString = "test" + val expectedResults = arrayOf("testsprite2","finish tests","testlook3","testlook4", + "testsound3","testsound4","testsprite3","testscene2", + "testsprite5","testscene3") + Espresso.onView(withId(R.id.myProjectsTextView)).perform(click()) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + + Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation() + .targetContext) + Espresso.onView(withText(R.string.search)).perform(click()) + + Espresso.onView(withId(R.id.search_bar)).perform(click()) + + val viewMatcher = Espresso.onView(withId(R.id.search_bar)).perform( + ViewActions.replaceText(queryString) + ) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + viewMatcher.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) + + for (i in expectedResults.indices) { + val currentFoundName = FinderDataManager.instance.getSearchResultsNames()?.get(i) + assertThat(currentFoundName, `is`(expectedResults[i])) + Espresso.onView(withId(R.id.find_next)).perform(click()) + } + for (i in expectedResults.indices.last downTo 0) { + val currentFoundName = FinderDataManager.instance.getSearchResultsNames()?.get(i) + assertThat(currentFoundName, `is`(expectedResults[i])) + Espresso.onView(withId(R.id.find_previous)).perform(click()) + } + } + + @Test + fun testSceneNotFindableOnLowerLevel(){ + + val queryString = "scene1" + + Espresso.onView(withId(R.id.myProjectsTextView)).perform(click()) + + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + + Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().targetContext) + Espresso.onView(withText(R.string.search)).perform(click()) + Espresso.onView(withId(R.id.search_bar)).perform(click()) + + val viewMatcher = Espresso.onView(withId(R.id.search_bar)).perform( + ViewActions.replaceText(queryString) + ) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + viewMatcher.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) + + assertThat(FinderDataManager.instance.currentMatchIndex, `is` (-1)) + } + @Test + fun testSpriteNotFindableOnLowerLevel(){ + + val queryString = "sprite" + + Espresso.onView(withId(R.id.myProjectsTextView)).perform(click()) + + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + Espresso.onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.actionOnItemAtPosition(0, click()) + ) + + Espresso.openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().targetContext) + Espresso.onView(withText(R.string.search)).perform(click()) + Espresso.onView(withId(R.id.search_bar)).perform(click()) + + val viewMatcher = Espresso.onView(withId(R.id.search_bar)).perform( + ViewActions.replaceText(queryString) + ) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + viewMatcher.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER)) + + assertThat(FinderDataManager.instance.currentMatchIndex, `is` (-1)) + } + + fun createProject(projectName: String?) { + val project = Project(ApplicationProvider.getApplicationContext(), projectName) + projectManager.currentProject = project + project.sceneList.clear() + val scene1Name = "scene1" + val scene2Name = "testScene2" + val scene3Name = "testScene3" + val scene4Name = "scene4" + + val scene1 = Scene(scene1Name, project) + val scene2 = Scene(scene2Name, project) + val scene3 = Scene(scene3Name, project) + val scene4 = Scene(scene4Name, project) + val sprite1 = Sprite("background") + val sprite2 = Sprite("testSprite2") + val sprite3 = Sprite("testSprite3") + val sprite4 = Sprite("background") + val sprite5 = Sprite("testSprite5") + project.addScene(scene1) + project.addScene(scene2) + project.addScene(scene3) + project.addScene(scene4) + project.getSceneByName(scene1Name).addSprite(sprite1) + project.getSceneByName(scene1Name).addSprite(sprite2) + project.getSceneByName(scene1Name).addSprite(sprite3) + project.getSceneByName(scene2Name).addSprite(sprite4) + project.getSceneByName(scene2Name).addSprite(sprite5) + + projectManager.apply { + setCurrentSceneAndSprite(scene1Name, sprite2.name) + currentSprite = sprite2 // Force update + currentlyEditedScene = project.getSceneByName(scene1Name) + } + + script = StartScript() + script.addBrick(FinishStageBrick()) + projectManager.currentSprite.addScript(script) + + ActionUtils.addSound(projectManager,"testSound3") + ActionUtils.addSound(projectManager, "Sound3") + ActionUtils.addSound(projectManager,"testSound4") + ActionUtils.addSound(projectManager, "Sound4") + ActionUtils.addLook(projectManager,"testLook3") + ActionUtils.addLook(projectManager, "Look3") + ActionUtils.addLook(projectManager,"testLook4") + ActionUtils.addLook(projectManager, "Look4") + + ProjectManager.getInstance().currentProject = project + } +} \ No newline at end of file diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt new file mode 100644 index 00000000000..05dd9fbd93c --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt @@ -0,0 +1,161 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2025 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.ui + +import android.content.Context +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.TextView +import org.catrobat.catroid.ProjectManager +import org.catrobat.catroid.R +import org.catrobat.catroid.common.Nameable +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene +import org.catrobat.catroid.content.Sprite +import org.catrobat.catroid.ui.recyclerview.fragment.RecyclerViewFragment +import org.koin.android.ext.android.inject + +abstract class BaseFinderFragment : RecyclerViewFragment() { + + protected val projectManager: ProjectManager by inject() + protected lateinit var currentProject: Project + protected lateinit var currentScene: Scene + protected lateinit var currentSprite: Sprite + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val parentView = super.onCreateView(inflater, container, savedInstanceState) + activity = getActivity() as SpriteActivity? + recyclerView = parentView!!.findViewById(R.id.recycler_view) + currentProject = projectManager.currentProject + currentScene = projectManager.currentlyEditedScene + currentSprite = projectManager.currentSprite + + setupFinderListeners() + + if (FinderDataManager.instance.getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + val sceneAndSpriteName = createActionBarTitle(1) + finder?.onFragmentChanged(sceneAndSpriteName) + scrollToSearchResult() + } + + return parentView + } + + private fun setupFinderListeners() { + finder?.setOnResultFoundListener(object : Finder.OnResultFoundListener { + override fun onResultFound( + sceneIndex: Int, + spriteIndex: Int, + brickIndex: Int, + type: Int, + totalResults: Int, + textView: TextView? + ) { + currentProject = projectManager.currentProject + currentScene = currentProject.sceneList[sceneIndex] + FinderDataManager.instance.type = type + + if (type == FinderDataManager.FragmentType.SPRITE.id) { + textView?.text = createActionBarTitle(2) + } else { + currentSprite = currentScene.spriteList[spriteIndex] + textView?.text = createActionBarTitle(1) + } + + FinderDataManager.instance.currentMatchIndex = brickIndex + + when (type) { + 1 -> activity.onBackPressed() + 2 -> { + projectManager.setCurrentlyEditedScene(currentScene) + activity.onBackPressed() + } + 3 -> { + projectManager.setCurrentSceneAndSprite(currentScene.name, currentSprite.name) + activity.loadFragment(0) + } + 4 -> { + projectManager.setCurrentSceneAndSprite(currentScene.name, currentSprite.name) + activity.loadFragment(1) + } + 5 -> { + projectManager.setCurrentSceneAndSprite(currentScene.name, currentSprite.name) + activity.loadFragment(2) + } + } + + hideKeyboard() + } + }) + + finder?.setOnCloseListener(object : Finder.OnCloseListener { + override fun onClose() { + finishActionMode() + if (!activity.isFinishing) { + activity.setCurrentSceneAndSprite( + projectManager.currentlyEditedScene, + projectManager.currentSprite + ) + activity.supportActionBar?.title = createActionBarTitle(1) + activity.addTabs() + } + activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + } + }) + + finder?.setOnOpenListener(object : Finder.OnOpenListener { + override fun onOpen() { + if (FinderDataManager.instance.getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { + finder.setInitiatingFragment(getFragmentType()) + FinderDataManager.instance.setSearchOrder(getSearchOrder()) + } + activity.removeTabs() + activity.findViewById(R.id.toolbar).visibility = View.GONE + } + }) + } + + fun createActionBarTitle(flag: Int): String { + return if(flag == 1) { + if (currentProject.sceneList != null && currentProject.sceneList.size == 1) { + currentSprite.name + } else { + currentScene.name + ": " + currentSprite.name + } + } else{ + currentScene.name + } + } + + private fun hideKeyboard() { + val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(requireView().windowToken, 0) + } + + protected abstract fun getFragmentType(): FinderDataManager.FragmentType + protected abstract fun getSearchOrder(): Array +} diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/ScriptFinder.kt b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt similarity index 53% rename from catroid/src/main/java/org/catrobat/catroid/ui/ScriptFinder.kt rename to catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt index 37a677186ef..0325e7c531f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/ScriptFinder.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt @@ -49,24 +49,19 @@ import org.koin.java.KoinJavaComponent.inject import java.util.ArrayList import java.util.Locale -class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { +class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) { private var onResultFoundListener: OnResultFoundListener? = null private var onCloseListener: OnCloseListener? = null private var onOpenListener: OnOpenListener? = null private val projectManager: ProjectManager by inject(ProjectManager::class.java) - - private var searchResults: MutableList>? = null - private var searchResultIndex = 0 - private var searchQuery = "" - private var binding: ViewScriptFinderBinding - private fun showNavigationButtons() { + fun showNavigationButtons() { + binding.find.visibility = GONE binding.findNext.visibility = VISIBLE binding.findPrevious.visibility = VISIBLE binding.searchPositionIndicator.visibility = VISIBLE - binding.find.visibility = GONE } private fun hideNavigationButtons() { @@ -77,7 +72,7 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } private fun formatSearchQuery(query: CharSequence): String = query.toString().trim() - .toLowerCase(Locale.ROOT) + .lowercase(Locale.ROOT) init { orientation = VERTICAL @@ -93,8 +88,9 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit - override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: Int) { - if (searchQuery == formatSearchQuery(newText)) { + override fun onTextChanged(newText: CharSequence, start: Int, before: Int, count: + Int) { + if (FinderDataManager.instance.getSearchQuery() == formatSearchQuery(newText)) { showNavigationButtons() } else { hideNavigationButtons() @@ -114,30 +110,34 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } companion object { - val TAG = ScriptFinder::class.java.simpleName + val TAG = Finder::class.java.simpleName @Suppress("ComplexMethod", "TooGenericExceptionCaught") fun searchBrickViews(v: View?, searchQuery: String): Boolean { try { - if (v is Spinner) { - val selectedItem = v.selectedItem - if (selectedItem is Nameable && selectedItem.name.toLowerCase(Locale.ROOT) - .contains(searchQuery) - ) { - return true + when (v) { + is Spinner -> { + val selectedItem = v.selectedItem + if (selectedItem is Nameable && selectedItem.name.lowercase(Locale.ROOT).contains(searchQuery)) { + FinderDataManager.instance.addtoSearchResultsNames(selectedItem.name.lowercase(Locale.ROOT)) + return true + } } - } else if (v is ViewGroup) { - for (i in 0 until v.childCount) { - val child = v.getChildAt(i) - val queryFoundInBrick = searchBrickViews(child, searchQuery) - if (queryFoundInBrick) { + + is ViewGroup -> { + for (i in 0 until v.childCount) { + val child = v.getChildAt(i) + val queryFoundInBrick = searchBrickViews(child, searchQuery) + if (queryFoundInBrick) return true + } + } + + is TextView -> { + if (v.text.toString().lowercase(Locale.ROOT).contains(searchQuery)) { + FinderDataManager.instance.addtoSearchResultsNames(v.text.toString().lowercase(Locale.ROOT)) return true } } - } else if (v is TextView && v.text.toString().toLowerCase(Locale.ROOT) - .contains(searchQuery) - ) { - return true } } catch (e: NullPointerException) { Log.e(TAG, Log.getStackTraceString(e)) @@ -149,13 +149,14 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex private fun find() { val query = formatSearchQuery(binding.searchBar.text) if (query.isNotEmpty()) { - if (searchQuery != query) { - searchQuery = query + if (FinderDataManager.instance.getSearchQuery() != query) { + FinderDataManager.instance.setSearchQuery(query) + binding.searchBar.setText(query) fillIndices(query) binding.find.visibility = GONE binding.findNext.visibility = VISIBLE binding.findPrevious.visibility = VISIBLE - } else if (searchResults != null) { + } else { findNext() } } else { @@ -167,9 +168,9 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } private fun findNext() { - searchResults?.let { + FinderDataManager.instance.getSearchResults().let { if (it.isNotEmpty()) { - searchResultIndex = (searchResultIndex + 1) % it.size + FinderDataManager.instance.setSearchResultIndex((FinderDataManager.instance.getSearchResultIndex() + 1) % it.size) updateUI() } else { binding.searchPositionIndicator.text = "0/0" @@ -179,10 +180,11 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } private fun findPrevious() { - searchResults?.let { + FinderDataManager.instance.getSearchResults().let { if (it.isNotEmpty()) { - searchResultIndex = - if (searchResultIndex == 0) it.size - 1 else searchResultIndex - 1 + FinderDataManager.instance.setSearchResultIndex(if (FinderDataManager.instance + .getSearchResultIndex() == 0) + it.size - 1 else FinderDataManager.instance.getSearchResultIndex() - 1) updateUI() } else { binding.searchPositionIndicator.text = "0/0" @@ -191,17 +193,26 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } } + fun onFragmentChanged(sceneAndSpriteName:String) { + openForChangeFragment() + + binding.searchPositionIndicator.text = String.format( + Locale.ROOT, "%d/%d", FinderDataManager.instance.getSearchResultIndex() + 1, + FinderDataManager.instance.getSearchResults().size + ) + binding.sceneAndSpriteName.text = sceneAndSpriteName + } private fun updateUI() { - val result = searchResults?.get(searchResultIndex) + val result = FinderDataManager.instance.getSearchResults().get(FinderDataManager.instance.getSearchResultIndex()) binding.searchPositionIndicator.text = String.format( - Locale.ROOT, "%d/%d", searchResultIndex + 1, - searchResults?.size + Locale.ROOT, "%d/%d", FinderDataManager.instance.getSearchResultIndex() + 1, + FinderDataManager.instance.getSearchResults().size ) - result?.let { - searchResults?.size?.let { it1 -> + result.let { + FinderDataManager.instance.getSearchResults().size.let { it1 -> onResultFoundListener?.onResultFound( - it[0], it[1], it[2], it1, + it[0], it[1], it[2],it[3], it1, binding.sceneAndSpriteName ) } @@ -209,19 +220,16 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } fun fillIndices(query: String) { - searchResultIndex = -1 + FinderDataManager.instance.setSearchResultIndex(-1) val activeScene = projectManager.currentlyEditedScene - val activeSprite = projectManager.currentSprite + val activeSprite: Sprite? = projectManager.currentSprite - if (searchResults != null) { - searchResults?.clear() - } else { - searchResults = ArrayList() - } + FinderDataManager.instance.clearSearchResults() + FinderDataManager.instance.clearSearchResultsNames() startThreadToFillIndices(query, activeScene, activeSprite) } - private fun startThreadToFillIndices(query: String, activeScene: Scene, activeSprite: Sprite) { + private fun startThreadToFillIndices(query: String, activeScene: Scene, activeSprite: Sprite?) { Thread { val activity = context as Activity if (!activity.isFinishing) { @@ -233,8 +241,14 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex } } val scenes = projectManager.currentProject.sceneList + for (i in scenes.indices) { val scene = scenes[i] + if (scene.name.lowercase(Locale.ROOT).contains(query)){ + FinderDataManager.instance.addtoSearchResults(arrayOf(i, i, i, + FinderDataManager.FragmentType.SCENE.id)) + FinderDataManager.instance.addtoSearchResultsNames(scene.name.lowercase(Locale.ROOT)) + } val spriteList = scene.spriteList for (j in spriteList.indices) { val sprite = spriteList[j] @@ -248,10 +262,42 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex script.setParents() script.addToFlatList(bricks) } - for (k in bricks.indices) { - val brick = bricks[k] - if (searchBrickViews(brick.getView(context), query)) { - searchResults?.add(arrayOf(i, j, k)) + for (order in FinderDataManager.instance.getSearchOrder()){ + when (order) { + 2 -> { + if (sprite.name.lowercase(Locale.ROOT).contains(query)){ + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, j, FinderDataManager.FragmentType.SPRITE.id)) + FinderDataManager.instance.addtoSearchResultsNames(sprite.name.lowercase(Locale.ROOT)) + } + } + 3 -> { + for (k in bricks.indices) { + val brick = bricks[k] + if (searchBrickViews(brick.getView(context), query)) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.SCRIPT.id)) + } + } + } + 4 -> { + val lookList = sprite.lookList + for (k in lookList.indices) { + val look = lookList[k] + if (look.name.lowercase(Locale.ROOT).contains(query)) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.LOOK.id)) + FinderDataManager.instance.addtoSearchResultsNames(look.name.lowercase(Locale.ROOT)) + } + } + } + 5 -> { + val soundList = sprite.soundList + for (k in soundList.indices) { + val sound = soundList[k] + if (sound.name.lowercase(Locale.ROOT).contains(query)) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.SOUND.id)) + FinderDataManager.instance.addtoSearchResultsNames(sound.name.lowercase(Locale.ROOT)) + } + } + } } } } @@ -262,10 +308,12 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex binding.findPrevious.visibility = VISIBLE binding.searchPositionIndicator.visibility = VISIBLE binding.progressBar.visibility = GONE - projectManager.setCurrentSceneAndSprite( - activeScene.name, - activeSprite.name - ) + if (activeSprite != null){ + projectManager.setCurrentSceneAndSprite( + activeScene.name, + activeSprite.name + ) + } findNext() } } @@ -275,25 +323,44 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex val isOpen: Boolean get() = visibility == VISIBLE + fun setInitiatingFragment(fragmentEnum: FinderDataManager.FragmentType){ + FinderDataManager.instance.setInitiatingFragment(fragmentEnum) + } fun open() { this.visibility = VISIBLE - val inputMethodManager = - context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + binding.searchBar.isFocusable + val inputMethodManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.toggleSoftInputFromWindow( - binding.searchBar.applicationWindowToken, - InputMethodManager.SHOW_FORCED, 0 - ) + binding.searchBar.applicationWindowToken, + InputMethodManager.SHOW_FORCED, 0 + ) + onOpenListener?.onOpen() + binding.searchBar.requestFocus() + } + fun disableFocusSearchBar(){ + binding.searchBar.isFocusable = false + } + + private fun openForChangeFragment(){ + this.visibility = VISIBLE + showNavigationButtons() onOpenListener?.onOpen() - binding.searchBar.requestFocus() + binding.searchBar.setText(FinderDataManager.instance.getSearchQuery()) + binding.searchBar.isFocusable = false } fun close() { this.visibility = GONE - searchResults?.clear() - - binding.searchBar.setText("") - searchQuery = "" + FinderDataManager.instance.clearSearchResults() + FinderDataManager.instance.clearSearchResultsNames() + binding.searchBar.text.clear() + binding.searchBar.isFocusableInTouchMode = true + FinderDataManager.instance.setSearchQuery(null) + FinderDataManager.instance.setInitiatingFragment(FinderDataManager.FragmentType.NONE) + FinderDataManager.instance.type = -1 + FinderDataManager.instance.currentMatchIndex = -1 onCloseListener?.onClose() + hideNavigationButtons() this.hideKeyboard() } @@ -317,6 +384,7 @@ class ScriptFinder(context: Context, attrs: AttributeSet?) : LinearLayout(contex sceneIndex: Int, spriteIndex: Int, brickIndex: Int, + type: Int, totalResults: Int, textView: TextView? ) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt b/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt new file mode 100644 index 00000000000..88a0e779cae --- /dev/null +++ b/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt @@ -0,0 +1,102 @@ +/* + * Catroid: An on-device visual programming system for Android devices + * Copyright (C) 2010-2024 The Catrobat Team + * () + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * An additional term exception under section 7 of the GNU Affero + * General Public License, version 3, is available at + * http://developer.catrobat.org/license_additional_term + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package org.catrobat.catroid.ui + +import java.util.ArrayList + +class FinderDataManager { + companion object { + val instance:FinderDataManager by lazy { + FinderDataManager() + } + } + enum class FragmentType(val id: Int){ + NONE(0), + SCENE(1), + SPRITE(2), + SCRIPT(3), + LOOK(4), + SOUND(5) + } + + private var initiatingfragment:FragmentType = FragmentType.NONE + private var searchResults = mutableListOf>() + private val searchResultsNames = mutableListOf() + private var searchResultIndex = -1 + private var searchQuery: String? = null + private var searchOrder = arrayOf(-1, -1) + var currentMatchIndex = -1 + var type = -1 + + fun getSearchOrder(): Array{ + return searchOrder + } + + fun setSearchOrder(order: Array){ + searchOrder = order + } + fun setSearchQuery(searchquery: String?){ + searchQuery = searchquery + } + + fun getSearchQuery(): String? { + return searchQuery + } + fun setSearchResultIndex(searchresultIndex:Int){ + searchResultIndex = searchresultIndex + } + + fun getSearchResultIndex(): Int{ + return searchResultIndex + } + fun addtoSearchResults(array: Array){ + searchResults.add(array) + } + fun addtoSearchResultsNames(item: String){ + searchResultsNames.add(item) + } + fun getInitiatingFragment(): FragmentType { + return initiatingfragment + } + + fun setInitiatingFragment(initiatingFragment:FragmentType){ + initiatingfragment = initiatingFragment + } + + fun clearSearchResults(){ + searchResults.clear() + } + + fun getSearchResults(): MutableList> { + return searchResults + } + + fun clearSearchResultsNames(){ + searchResultsNames.clear() + } + + fun getSearchResultsNames(): MutableList { + return searchResultsNames + } +} \ No newline at end of file diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java b/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java index da15cc5ba8f..c3d51c0adbc 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/SpriteActivity.java @@ -289,14 +289,6 @@ public void onBackPressed() { ((ScriptFragment) currentFragment).cancelMove(); return; } - if (((ScriptFragment) currentFragment).isFinderOpen()) { - ((ScriptFragment) currentFragment).closeFinder(); - return; - } - if (((ScriptFragment) currentFragment).isCurrentlyHighlighted()) { - ((ScriptFragment) currentFragment).cancelHighlighting(); - return; - } } else if (currentFragment instanceof FormulaEditorFragment) { ((FormulaEditorFragment) currentFragment).exitFormulaEditorFragment(); return; diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt index eec771f78d9..c4166a2b976 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/LookAdapter.kt @@ -25,6 +25,7 @@ package org.catrobat.catroid.ui.recyclerview.adapter import android.view.View import org.catrobat.catroid.R import org.catrobat.catroid.common.LookData +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder import org.catrobat.catroid.utils.FileMetaDataExtractor import java.util.Locale @@ -34,6 +35,11 @@ class LookAdapter(items: List?) : ExtendedRVAdapter(items) val item = items[position] holder.title.text = item?.name holder.image.setImageBitmap(item?.thumbnailBitmap) + if (position == FinderDataManager.instance.currentMatchIndex) { + holder.itemView.setBackgroundResource(R.drawable.button_background_pressed) + } else { + holder.itemView.setBackgroundResource(R.drawable.button_background_selector) + } if (showDetails) { val measure = item?.measure val measureString = measure?.get(0).toString() + " x " + measure?.get(1) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java index 9808f85ea66..0f3e22a02e4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/MultiViewSpriteAdapter.java @@ -35,6 +35,7 @@ import org.catrobat.catroid.content.GroupItemSprite; import org.catrobat.catroid.content.GroupSprite; import org.catrobat.catroid.content.Sprite; +import org.catrobat.catroid.ui.FinderDataManager; import org.catrobat.catroid.ui.recyclerview.viewholder.CheckableViewHolder; import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder; @@ -102,15 +103,30 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { context.getTheme()); holder.image.setImageDrawable(drawable); holder.checkBox.setVisibility(GONE); + if(isThisFoundObject(position)){ + highlightTheFoundObject(holder); + } + else{ + cancelHighlightTheFoundObject(holder); + } return; } - if (holder.getItemViewType() == BACKGROUND) { + else if (holder.getItemViewType() == BACKGROUND) { holder.itemView.setOnLongClickListener(null); holder.checkBox.setVisibility(GONE); + if (isThisFoundObject(position)) { + View viewBackgroundButton = + holder.itemView.findViewById(R.id.view_holder_background); + viewBackgroundButton.setBackgroundResource(R.drawable.button_background_pressed); + } + else{ + View viewBackgroundButton = holder.itemView.findViewById(R.id.view_holder_background); + viewBackgroundButton.setBackgroundResource(R.drawable.button_background_selector); + } } - if (holder.getItemViewType() == SPRITE_GROUP_ITEM) { + else if (holder.getItemViewType() == SPRITE_GROUP_ITEM) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams .MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); holder.itemView.setLayoutParams(params); @@ -118,6 +134,21 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { params.height = 0; holder.itemView.setLayoutParams(params); } + if(isThisFoundObject(position)){ + highlightTheFoundObject(holder); + } + else{ + cancelHighlightTheFoundObject(holder); + } + } + + else{ + if(isThisFoundObject(position)){ + highlightTheFoundObject(holder); + } + else{ + cancelHighlightTheFoundObject(holder); + } } Bitmap lookData = null; @@ -126,6 +157,7 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { } holder.image.setImageBitmap(lookData); + if (showDetails) { holder.details.setText(String.format(Locale.getDefault(), context.getString(R.string.sprite_details), @@ -137,7 +169,15 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { holder.details.setVisibility(GONE); } } - + private boolean isThisFoundObject(int position){ + return position == FinderDataManager.Companion.getInstance().getCurrentMatchIndex(); + } + private void cancelHighlightTheFoundObject(ExtendedViewHolder holder){ + holder.itemView.setBackgroundResource(R.drawable.button_background_selector); + } + private void highlightTheFoundObject(ExtendedViewHolder holder){ + holder.itemView.setBackgroundResource(R.drawable.button_background_pressed); + } @Override public @ViewType int getItemViewType(int position) { if (position == 0) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java index 0c73bc1d912..c436958796c 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SceneAdapter.java @@ -23,6 +23,7 @@ package org.catrobat.catroid.ui.recyclerview.adapter; +import android.graphics.Color; import android.view.View; import org.catrobat.catroid.ProjectManager; @@ -30,12 +31,15 @@ import org.catrobat.catroid.content.Scene; import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.io.ProjectAndSceneScreenshotLoader; +import org.catrobat.catroid.ui.FinderDataManager; import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder; import java.io.File; import java.util.List; import java.util.Locale; +import static android.view.View.GONE; + public class SceneAdapter extends ExtendedRVAdapter { public SceneAdapter(List items) { @@ -54,6 +58,12 @@ public void onBindViewHolder(ExtendedViewHolder holder, int position) { loader.loadAndShowScreenshot(projectDir.getName(), item.getDirectory().getName(), false, holder.image); + if (position == FinderDataManager.Companion.getInstance().getCurrentMatchIndex()) { + holder.itemView.setBackgroundResource(R.drawable.button_background_pressed); + } else { + holder.itemView.setBackgroundResource(R.drawable.button_background_selector); + } + if (showDetails) { holder.details.setText(String.format(Locale.getDefault(), holder.itemView.getContext().getString(R.string.scene_details), diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt index 32fb683067a..0f438463748 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SoundAdapter.kt @@ -28,6 +28,7 @@ import android.text.format.DateUtils import android.util.Log import org.catrobat.catroid.R import org.catrobat.catroid.common.SoundInfo +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder import org.catrobat.catroid.utils.FileMetaDataExtractor import java.io.IOException @@ -47,6 +48,12 @@ class SoundAdapter(items: List?) : ExtendedRVAdapter(ite holder?.title?.text = item?.name holder?.image?.setImageResource(R.drawable.ic_media_play_dark) + if (position == FinderDataManager.instance.currentMatchIndex) { + holder?.itemView?.setBackgroundResource(R.drawable.button_background_pressed) + } else { + holder?.itemView?.setBackgroundResource(R.drawable.button_background_selector) + } + holder?.image?.setOnClickListener { if (mediaPlayer.isPlaying) { holder.image.setImageResource(R.drawable.ic_media_play_dark) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java index 271733da3bf..3b1a103ffd9 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/adapter/SpriteAdapter.java @@ -31,6 +31,7 @@ import org.catrobat.catroid.content.Sprite; import org.catrobat.catroid.ui.recyclerview.viewholder.ExtendedViewHolder; + import java.util.List; import java.util.Locale; diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt index e347551b89a..a5736e99882 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt @@ -36,6 +36,8 @@ import org.catrobat.catroid.common.Constants import org.catrobat.catroid.common.LookData import org.catrobat.catroid.common.SharedPreferenceKeys.SHOW_DETAILS_LOOKS_PREFERENCE_KEY import org.catrobat.catroid.io.StorageOperations +import org.catrobat.catroid.ui.BaseFinderFragment +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.SpriteActivity import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.controller.BackpackListManager @@ -49,17 +51,23 @@ import org.koin.android.ext.android.inject import java.io.IOException import java.util.ArrayList -class LookListFragment : RecyclerViewFragment() { +class LookListFragment : BaseFinderFragment() { private val lookController = LookController() private var currentItem: LookData? = null - private val projectManager: ProjectManager by inject() - companion object { @JvmField val TAG = LookListFragment::class.java.simpleName } + override fun getFragmentType(): FinderDataManager.FragmentType { + return FinderDataManager.FragmentType.LOOK + } + + override fun getSearchOrder(): Array { + return arrayOf(2, 4, 5, 3) + } + override fun initializeAdapter() { sharedPreferenceDetailsKey = SHOW_DETAILS_LOOKS_PREFERENCE_KEY val items = projectManager.currentSprite.lookList @@ -72,7 +80,7 @@ class LookListFragment : RecyclerViewFragment() { super.onPrepareOptionsMenu(menu) menu.findItem(R.id.catblocks_reorder_scripts).isVisible = false menu.findItem(R.id.catblocks).isVisible = false - menu.findItem(R.id.find).isVisible = false + menu.findItem(R.id.find).isVisible = true } override fun onResume() { @@ -253,6 +261,7 @@ class LookListFragment : RecyclerViewFragment() { R.id.project_options, R.id.edit, R.id.from_local, + R.id.find ) val popupMenu = UiUtils.createSettingsPopUpMenu(view, requireContext(), R.menu .menu_project_activity, hiddenOptionMenuIds) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java index d1a72a6942c..b8da482d67a 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/RecyclerViewFragment.java @@ -39,6 +39,8 @@ import org.catrobat.catroid.common.Nameable; import org.catrobat.catroid.merge.NewProjectNameTextWatcher; import org.catrobat.catroid.ui.BottomBar; +import org.catrobat.catroid.ui.Finder; +import org.catrobat.catroid.ui.SpriteActivity; import org.catrobat.catroid.ui.controller.BackpackListManager; import org.catrobat.catroid.ui.recyclerview.adapter.ExtendedRVAdapter; import org.catrobat.catroid.ui.recyclerview.adapter.MultiViewSpriteAdapter; @@ -50,6 +52,7 @@ import org.catrobat.catroid.ui.recyclerview.util.UniqueNameProvider; import org.catrobat.catroid.ui.recyclerview.viewholder.CheckableViewHolder; import org.catrobat.catroid.utils.ToastUtil; +import org.catrobat.catroid.ui.FinderDataManager; import org.jetbrains.annotations.NotNull; import java.lang.annotation.Retention; @@ -88,6 +91,9 @@ public abstract class RecyclerViewFragment extends Fragment protected View parentView; protected RecyclerView recyclerView; + protected Finder finder; + protected SpriteActivity activity; + protected TextView emptyView; protected ExtendedRVAdapter adapter; @@ -239,6 +245,7 @@ protected void resetActionModeParameters() { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { parentView = inflater.inflate(R.layout.fragment_list_view, container, false); + finder = parentView.findViewById(R.id.findview); recyclerView = parentView.findViewById(R.id.recycler_view); emptyView = parentView.findViewById(R.id.empty_view); setShowProgressBar(true); @@ -349,6 +356,9 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.merge: startActionMode(MERGE); break; + case R.id.find: + finder.open(); + break; case R.id.show_details: adapter.showDetails = !adapter.showDetails; PreferenceManager.getDefaultSharedPreferences(getActivity()) @@ -580,4 +590,20 @@ protected void mergeProjects(List selectedProjects, String mergeProjectName) ToastUtil.showSuccess(getContext(), R.string.merging_project_text); finishActionMode(); } + + protected void scrollToSearchResult() { + int indexSearch = FinderDataManager.Companion.getInstance().getSearchResultIndex(); + List searchResults = + FinderDataManager.Companion.getInstance().getSearchResults(); + + if (searchResults != null && indexSearch < searchResults.size()) { + Integer[] result = searchResults.get(indexSearch); + if (result != null && result.length > 2) { + Integer value = result[2]; + if (value != null) { + recyclerView.scrollToPosition(value); + } + } + } + } } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt index 50a2fe889ef..880b52a342a 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt @@ -22,21 +22,32 @@ */ package org.catrobat.catroid.ui.recyclerview.fragment +import android.content.Context import android.content.Intent import android.util.Log import android.view.Menu +import android.os.Bundle import android.view.View import androidx.annotation.PluralsRes import androidx.appcompat.app.AppCompatActivity import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R import org.catrobat.catroid.common.Constants +import android.view.LayoutInflater +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.TextView + import org.catrobat.catroid.common.SharedPreferenceKeys +import org.catrobat.catroid.content.Project import org.catrobat.catroid.content.Scene import org.catrobat.catroid.content.Sprite import org.catrobat.catroid.io.XstreamSerializer import org.catrobat.catroid.io.asynctask.ProjectLoader.ProjectLoadListener import org.catrobat.catroid.io.asynctask.loadProject +import org.catrobat.catroid.ui.FinderDataManager +import org.catrobat.catroid.ui.ProjectActivity +import org.catrobat.catroid.ui.Finder import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.controller.BackpackListManager import org.catrobat.catroid.ui.recyclerview.adapter.SceneAdapter @@ -53,8 +64,70 @@ class SceneListFragment : RecyclerViewFragment(), private val sceneController = SceneController() private val projectManager: ProjectManager by inject() + private lateinit var currentProject: Project + private lateinit var currentScene: Scene + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val parentView = super.onCreateView(inflater, container, savedInstanceState) + val activity = getActivity() as ProjectActivity + recyclerView = parentView!!.findViewById(R.id.recycler_view) + currentProject = ProjectManager.getInstance().currentProject + currentScene = ProjectManager.getInstance().currentlyEditedScene + + finder?.setOnResultFoundListener(object : Finder.OnResultFoundListener { + override fun onResultFound( + sceneIndex: Int, + spriteIndex: Int, + brickIndex: Int, + type: Int, + totalResults: Int, + textView: TextView? + ) { + + currentScene = currentProject.sceneList[sceneIndex] + FinderDataManager.instance.type = type + FinderDataManager.instance.currentMatchIndex = brickIndex + + if (type != FinderDataManager.FragmentType.SCENE.id) { + onItemClick(currentScene,MultiSelectionManager()) + } else { + textView?.text = createActionBarTitle() + initializeAdapter() + adapter.notifyDataSetChanged() + scrollToSearchResult() + finder.disableFocusSearchBar() + } + hideKeyboard() + } + }) + finder?.setOnCloseListener(object : Finder.OnCloseListener { + override fun onClose() { + activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + finishActionMode() + } + }) + + finder?.setOnOpenListener(object : Finder.OnOpenListener { + override fun onOpen() { + activity.findViewById(R.id.toolbar).visibility = View.GONE + finder.setInitiatingFragment(FinderDataManager.FragmentType.SCENE) + val order = arrayOf(2, 3, 4, 5) + FinderDataManager.instance.setSearchOrder(order) + } + }) + + return parentView + } + fun createActionBarTitle(): String { + return currentProject.name + } + private fun hideKeyboard() { + val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(requireView().windowToken, 0) + } override fun onResume() { super.onResume() + val currentProject = projectManager.currentProject if (currentProject.sceneList.size < 2) { projectManager.currentlyEditedScene = currentProject.defaultScene @@ -62,8 +135,17 @@ class SceneListFragment : RecyclerViewFragment(), } projectManager.currentlyEditedScene = currentProject.defaultScene (requireActivity() as AppCompatActivity).supportActionBar?.title = currentProject.name - } + if (FinderDataManager.instance.getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + val sceneAndSpriteName = createActionBarTitle() + finder.onFragmentChanged(sceneAndSpriteName) + scrollToSearchResult() + hideKeyboard() + } + else{ + finder.close() + } + } private fun switchToSpriteListFragment() { parentFragmentManager.beginTransaction() .replace(R.id.fragment_container, SpriteListFragment(), SpriteListFragment.TAG) @@ -232,6 +314,7 @@ class SceneListFragment : RecyclerViewFragment(), R.id.project_options, R.id.edit, R.id.from_local, + R.id.find ) val popupMenu = UiUtils.createSettingsPopUpMenu(view, requireContext(), R.menu .menu_project_activity, hiddenOptionMenuIds) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index 202d3c0403e..63cc5b74b80 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -40,6 +40,7 @@ import android.widget.ListAdapter; import org.catrobat.catroid.BuildConfig; + import org.catrobat.catroid.ProjectManager; import org.catrobat.catroid.R; import org.catrobat.catroid.common.ScreenValues; @@ -64,8 +65,10 @@ import org.catrobat.catroid.io.asynctask.ProjectLoader; import org.catrobat.catroid.io.asynctask.ProjectSaver; import org.catrobat.catroid.ui.BottomBar; -import org.catrobat.catroid.ui.ScriptFinder; +import org.catrobat.catroid.ui.FinderDataManager; +import org.catrobat.catroid.ui.Finder; import org.catrobat.catroid.ui.SpriteActivity; +import org.catrobat.catroid.ui.SpriteActivityOnTabSelectedListenerKt; import org.catrobat.catroid.ui.UiUtils; import org.catrobat.catroid.ui.controller.BackpackListManager; import org.catrobat.catroid.ui.controller.RecentBrickListManager; @@ -137,7 +140,7 @@ public class ScriptFragment extends ListFragment implements private ActionMode actionMode; private BrickAdapter adapter; private BrickListView listView; - private ScriptFinder scriptFinder; + private Finder finder; private String currentSceneName; private String currentSpriteName; private int undoBrickPosition; @@ -274,7 +277,6 @@ private void resetActionModeParameters() { actionMode = null; adapter.setCheckBoxMode(BrickAdapter.NONE); } - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = View.inflate(getActivity(), R.layout.fragment_script, null); @@ -291,29 +293,58 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa activity = (SpriteActivity) getActivity(); SettingsFragment.setToChosenLanguage(activity); - scriptFinder = view.findViewById(R.id.findview); - scriptFinder.setOnResultFoundListener((sceneIndex, spriteIndex, brickIndex, totalResults, + finder = view.findViewById(R.id.findview); + finder.setOnResultFoundListener((sceneIndex, spriteIndex, brickIndex,type, + totalResults, textView ) -> { Project currentProject = ProjectManager.getInstance().getCurrentProject(); Scene currentScene = currentProject.getSceneList().get(sceneIndex); - Sprite currentSprite = currentScene.getSpriteList().get(spriteIndex); - - textView.setText(createActionBarTitle(currentProject, - currentScene, - currentSprite)); + Sprite currentSprite = null; + if(type != FinderDataManager.FragmentType.SCENE.getId()){ + currentSprite = currentScene.getSpriteList().get(spriteIndex); + ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), currentSprite.getName()); + } + FinderDataManager.Companion.getInstance().setType(type); - ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), - currentSprite.getName()); + if(type != FinderDataManager.FragmentType.SPRITE.getId() && type != FinderDataManager.FragmentType.SCENE.getId()) { + textView.setText(createActionBarTitle(currentProject, currentScene, currentSprite,1)); + } + else{ + textView.setText(createActionBarTitle(currentProject, currentScene, currentSprite,2)); + } - adapter.updateItems(currentSprite); - adapter.notifyDataSetChanged(); - listView.smoothScrollToPosition(brickIndex); - highlightBrickAtIndex(brickIndex); - hideKeyboard(); + FinderDataManager.Companion.getInstance().setCurrentMatchIndex(brickIndex); + + if(type != FinderDataManager.FragmentType.SCRIPT.getId()){ + switch (type){ + case 1: + activity.onBackPressed(); + break; + case 2: + ProjectManager.getInstance().setCurrentlyEditedScene(currentScene); + activity.onBackPressed(); + break; + case 4: + SpriteActivityOnTabSelectedListenerKt.loadFragment(activity,1); + ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), currentSprite.getName()); + break; + case 5: + SpriteActivityOnTabSelectedListenerKt.loadFragment(activity,2); + ProjectManager.getInstance().setCurrentSceneAndSprite(currentScene.getName(), currentSprite.getName()); + break; + } + } + else{ + adapter.updateItems(currentSprite); + adapter.notifyDataSetChanged(); + listView.smoothScrollToPosition(brickIndex); + highlightBrickAtIndex(brickIndex); + hideKeyboard(); + } }); - scriptFinder.setOnCloseListener(() -> { + finder.setOnCloseListener(() -> { listView.cancelHighlighting(); finishActionMode(); if (activity != null && !activity.isFinishing()) { @@ -325,20 +356,43 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa activity.findViewById(R.id.toolbar).setVisibility(View.VISIBLE); }); - scriptFinder.setOnOpenListener(() -> { + finder.setOnOpenListener(() -> { + if (FinderDataManager.Companion.getInstance().getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { + finder.setInitiatingFragment(FinderDataManager.FragmentType.SCRIPT); + Integer[] order = {2, 3, 4, 5}; + FinderDataManager.Companion.getInstance().setSearchOrder(order); + } activity.removeTabs(); activity.findViewById(R.id.toolbar).setVisibility(View.GONE); }); + if (FinderDataManager.Companion.getInstance().getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + String sceneAndSpriteName = + createActionBarTitle(ProjectManager.getInstance().getCurrentProject(), + ProjectManager.getInstance().getStartScene(), + ProjectManager.getInstance().getCurrentSprite(),1); + finder.onFragmentChanged(sceneAndSpriteName); + int indexSearch = FinderDataManager.Companion.getInstance().getSearchResultIndex(); + int brickIndex = FinderDataManager.Companion.getInstance().getSearchResults().get(indexSearch)[2]; + listView.smoothScrollToPosition(brickIndex); + highlightBrickAtIndex(brickIndex); + } + setHasOptionsMenu(true); return view; } - public String createActionBarTitle(Project currentProject, Scene currentScene, Sprite currentSprite) { - if (currentProject.getSceneList().size() == 1) { - return currentSprite.getName(); - } else { - return currentScene.getName() + ": " + currentSprite.getName(); + public String createActionBarTitle(Project currentProject, Scene currentScene, + Sprite currentSprite, int flag) { + if(flag == 1) { + if (currentProject.getSceneList().size() == 1) { + return currentSprite.getName(); + } else { + return currentScene.getName() + ": " + currentSprite.getName(); + } + } + else{ + return currentScene.getName(); } } @@ -356,7 +410,7 @@ private void hideKeyboard() { @Override public void onDestroyView() { super.onDestroyView(); - if (scriptFinder.isOpen() && activity != null) { + if (finder.isOpen() && activity != null) { activity.findViewById(R.id.toolbar).setVisibility(View.VISIBLE); } } @@ -477,7 +531,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switchToCatblocks(); break; case R.id.find: - scriptFinder.open(); + finder.open(); break; default: return super.onOptionsItemSelected(item); @@ -1096,12 +1150,12 @@ public int getActionModeType() { } public boolean isFinderOpen() { - return scriptFinder.isOpen(); + return finder.isOpen(); } public void closeFinder() { - if (!scriptFinder.isClosed()) { - scriptFinder.close(); + if (!finder.isClosed()) { + finder.close(); } } } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt index 4b9779a48ee..89a8be024c4 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt @@ -28,11 +28,12 @@ import android.view.Menu import android.view.View import androidx.annotation.PluralsRes import org.catrobat.catroid.BuildConfig -import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R import org.catrobat.catroid.common.SharedPreferenceKeys import org.catrobat.catroid.common.SoundInfo import org.catrobat.catroid.pocketmusic.PocketMusicActivity +import org.catrobat.catroid.ui.BaseFinderFragment +import org.catrobat.catroid.ui.FinderDataManager import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.controller.BackpackListManager import org.catrobat.catroid.ui.recyclerview.adapter.SoundAdapter @@ -41,19 +42,26 @@ import org.catrobat.catroid.ui.recyclerview.backpack.BackpackActivity import org.catrobat.catroid.ui.recyclerview.controller.SoundController import org.catrobat.catroid.utils.SnackbarUtil import org.catrobat.catroid.utils.ToastUtil -import org.koin.android.ext.android.inject import java.io.IOException -class SoundListFragment : RecyclerViewFragment() { +class SoundListFragment : BaseFinderFragment() { private val soundController = SoundController() - private val projectManager: ProjectManager by inject() + companion object { @JvmField val TAG = SoundListFragment::class.java.simpleName } + override fun getFragmentType(): FinderDataManager.FragmentType { + return FinderDataManager.FragmentType.LOOK + } + + override fun getSearchOrder(): Array { + return arrayOf(2, 4, 5, 3) + } + override fun initializeAdapter() { sharedPreferenceDetailsKey = SharedPreferenceKeys.SHOW_DETAILS_SOUNDS_PREFERENCE_KEY val items = projectManager.currentSprite.soundList @@ -77,7 +85,7 @@ class SoundListFragment : RecyclerViewFragment() { menu.findItem(R.id.catblocks_reorder_scripts).isVisible = false menu.findItem(R.id.catblocks).isVisible = false - menu.findItem(R.id.find).isVisible = false + menu.findItem(R.id.find).isVisible = true } override fun packItems(selectedItems: List) { @@ -205,6 +213,7 @@ class SoundListFragment : RecyclerViewFragment() { R.id.project_options, R.id.edit, R.id.from_local, + R.id.find ) val popupMenu = UiUtils.createSettingsPopUpMenu(view, requireContext(), R.menu .menu_project_activity, hiddenOptionMenuIds) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt index ccb492c7819..13bf85a4ca9 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt @@ -24,14 +24,20 @@ package org.catrobat.catroid.ui.recyclerview.fragment import android.annotation.SuppressLint import android.app.Activity +import android.content.Context import android.content.DialogInterface import android.content.Intent import android.net.Uri +import android.os.Bundle import android.preference.PreferenceManager import android.util.Log +import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.TextView import androidx.annotation.PluralsRes import androidx.appcompat.app.AppCompatActivity import androidx.recyclerview.widget.ItemTouchHelper @@ -41,13 +47,19 @@ import org.catrobat.catroid.R import org.catrobat.catroid.common.Constants import org.catrobat.catroid.common.Constants.TMP_IMAGE_FILE_NAME import org.catrobat.catroid.common.SharedPreferenceKeys +import org.catrobat.catroid.content.GroupItemSprite import org.catrobat.catroid.content.GroupSprite +import org.catrobat.catroid.content.Project +import org.catrobat.catroid.content.Scene import org.catrobat.catroid.content.Sprite import org.catrobat.catroid.io.StorageOperations import org.catrobat.catroid.merge.ImportProjectHelper +import org.catrobat.catroid.ui.FinderDataManager +import org.catrobat.catroid.ui.ProjectActivity import org.catrobat.catroid.ui.ProjectListActivity import org.catrobat.catroid.ui.ProjectListActivity.Companion.IMPORT_LOCAL_INTENT import org.catrobat.catroid.ui.SpriteActivity +import org.catrobat.catroid.ui.Finder import org.catrobat.catroid.ui.UiUtils import org.catrobat.catroid.ui.WebViewActivity import org.catrobat.catroid.ui.controller.BackpackListManager @@ -73,6 +85,8 @@ class SpriteListFragment : RecyclerViewFragment() { private val projectManager: ProjectManager by inject() private var currentSprite: Sprite? = null + private lateinit var currentProject: Project + private lateinit var currentScene: Scene internal inner class MultiViewTouchHelperCallback(adapterInterface: TouchHelperAdapterInterface?) : TouchHelperCallback(adapterInterface) { @@ -105,10 +119,116 @@ class SpriteListFragment : RecyclerViewFragment() { public override fun shouldShowEmptyView() = adapter.itemCount == 1 override fun onResume() { + currentScene = ProjectManager.getInstance().currentlyEditedScene + initializeAdapter() + super.onResume() SnackbarUtil.showHintSnackbar(requireActivity(), R.string.hint_objects) - val currentProject = projectManager.currentProject + makeTitle() + + if (FinderDataManager.instance.getInitiatingFragment() != FinderDataManager.FragmentType.NONE) { + handleFinderDataManagerLogic() + if (FinderDataManager.instance.type != FinderDataManager.FragmentType.SCENE.id){ + unCollapseFoundObject(FinderDataManager.instance.currentMatchIndex) + } + } + else{ + finder.close() + } + } + + private fun handleFinderDataManagerLogic() { + val activity = getActivity() as ProjectActivity + + if(FinderDataManager.instance.type == FinderDataManager.FragmentType.SCENE.id){ + activity.onBackPressed() + } + else{ + val searchIndex = FinderDataManager.instance.getSearchResultIndex() + val spriteIndex = FinderDataManager.instance.getSearchResults()[searchIndex][1] + projectManager.currentSprite = currentScene.spriteList[spriteIndex] + + when (FinderDataManager.instance.type) { + FinderDataManager.FragmentType.SCENE.id -> activity.onBackPressed() + FinderDataManager.FragmentType.SPRITE.id -> {} + else -> startActivity(createSpriteActivityIntent(FinderDataManager.instance.type)) + } + } + val sceneAndSpriteName = createActionBarTitle() + finder.onFragmentChanged(sceneAndSpriteName) + scrollToSearchResult() + hideKeyboard() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + val parentView = super.onCreateView(inflater, container, savedInstanceState) + recyclerView = parentView!!.findViewById(R.id.recycler_view) + currentProject = ProjectManager.getInstance().currentProject + currentScene = ProjectManager.getInstance().currentlyEditedScene + val activity = getActivity() as ProjectActivity + + finder?.setOnResultFoundListener(object : Finder.OnResultFoundListener { + override fun onResultFound( + sceneIndex: Int, + spriteIndex: Int, + brickIndex: Int, + type: Int, + totalResults: Int, + textView: TextView? + ) { + + currentProject = ProjectManager.getInstance().currentProject + currentScene = currentProject.sceneList[sceneIndex] + ProjectManager.getInstance().setCurrentlyEditedScene(currentScene) + + makeTitle() + + FinderDataManager.instance.currentMatchIndex = brickIndex + + when (type) { + FinderDataManager.FragmentType.SPRITE.id -> { + textView?.text = createActionBarTitle() + initializeAdapter() + unCollapseFoundObject(spriteIndex) + adapter.notifyDataSetChanged() + scrollToSearchResult() + finder.disableFocusSearchBar() + + } + FinderDataManager.FragmentType.SCENE.id -> { + activity.onBackPressed() + } + else -> { + projectManager.currentSprite = currentProject.sceneList[sceneIndex].spriteList[spriteIndex] + val intent = createSpriteActivityIntent(type) + startActivity(intent) + } + } + hideKeyboard() + } + }) + + finder?.setOnCloseListener(object : Finder.OnCloseListener { + override fun onClose() { + finishActionMode() + activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + } + }) + + finder?.setOnOpenListener(object : Finder.OnOpenListener { + override fun onOpen() { + activity.findViewById(R.id.toolbar).visibility = View.GONE + finder.setInitiatingFragment(FinderDataManager.FragmentType.SPRITE) + val order = arrayOf(2,3,4,5) + FinderDataManager.instance.setSearchOrder(order) + } + }) + return parentView + } + + private fun makeTitle(){ + currentProject = ProjectManager.getInstance().currentProject val title: String = if (currentProject.sceneList.size < 2) { currentProject.name } else { @@ -120,6 +240,40 @@ class SpriteListFragment : RecyclerViewFragment() { (requireActivity() as AppCompatActivity).supportActionBar?.title = title } + private fun unCollapseFoundObject(spriteIndex: Int) { + + val currentItem = currentScene.spriteList[spriteIndex] + if (currentItem is GroupItemSprite && currentItem.isCollapsed){ + for (i in spriteIndex downTo 1) { + val groupItem = currentScene.spriteList[i] + if (groupItem is GroupSprite) { + groupItem.isCollapsed = false + break + } + } + } + } + + private fun createSpriteActivityIntent(type: Int): Intent { + val intent = Intent(requireContext(), SpriteActivity::class.java) + intent.putExtra( + SpriteActivity.EXTRA_FRAGMENT_POSITION, + when (type) { + FinderDataManager.FragmentType.SOUND.id -> SpriteActivity.FRAGMENT_SOUNDS + FinderDataManager.FragmentType.LOOK.id -> SpriteActivity.FRAGMENT_LOOKS + else -> SpriteActivity.FRAGMENT_SCRIPTS + } + ) + return intent + } + + fun createActionBarTitle(): String { + return currentScene.name + } + private fun hideKeyboard() { + val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(requireView().windowToken, 0) + } override fun onAdapterReady() { super.onAdapterReady() val callback: ItemTouchHelper.Callback = MultiViewTouchHelperCallback(adapter) @@ -130,6 +284,7 @@ class SpriteListFragment : RecyclerViewFragment() { override fun onPrepareOptionsMenu(menu: Menu) { super.onPrepareOptionsMenu(menu) menu.findItem(R.id.new_group).isVisible = true + menu.findItem(R.id.find).isVisible = true } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -142,8 +297,8 @@ class SpriteListFragment : RecyclerViewFragment() { } private fun handleSelectedOptionItem(item: MenuItem) { - if (adapter.items.size == 1) { - ToastUtil.showError(activity, R.string.am_empty_list) + if (adapter.items.size == 1 && item.title.toString() != "Search") { + ToastUtil.showError(getActivity(), R.string.am_empty_list) resetActionModeParameters() } else { super.onOptionsItemSelected(item) @@ -321,6 +476,9 @@ class SpriteListFragment : RecyclerViewFragment() { } override fun onItemClick(item: Sprite?, selectionManager: MultiSelectionManager?) { + if (finder.isOpen){ + finder.close() + } if (item is GroupSprite) { item.isCollapsed = !item.isCollapsed adapter.notifyDataSetChanged() @@ -352,7 +510,8 @@ class SpriteListFragment : RecyclerViewFragment() { val itemList = mutableListOf() itemList.add(item) val hiddenMenuOptionIds = mutableListOf( - R.id.new_group, R.id.project_options, R.id.new_scene, R.id.show_details, R.id.edit + R.id.new_group, R.id.project_options, R.id.new_scene, R.id.show_details, R.id.edit,R + .id.find ) if (item is GroupSprite) { hiddenMenuOptionIds.add(R.id.backpack) diff --git a/catroid/src/main/res/layout/fragment_list_view.xml b/catroid/src/main/res/layout/fragment_list_view.xml index 0cf9180b67f..a073205b61f 100644 --- a/catroid/src/main/res/layout/fragment_list_view.xml +++ b/catroid/src/main/res/layout/fragment_list_view.xml @@ -1,4 +1,3 @@ - - - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:visibility="gone"/> - - + android:layout_height="0dp" + android:layout_weight="1"> + + + + + + + - + diff --git a/catroid/src/main/res/layout/fragment_script.xml b/catroid/src/main/res/layout/fragment_script.xml index 7e4177c59b5..7db7aebc0f4 100644 --- a/catroid/src/main/res/layout/fragment_script.xml +++ b/catroid/src/main/res/layout/fragment_script.xml @@ -28,7 +28,7 @@ android:layout_weight="1" android:orientation="vertical" > - - + + + Date: Sun, 14 Sep 2025 17:28:49 +0200 Subject: [PATCH 4/5] Review corrections --- .../java/org/catrobat/catroid/ui/Finder.kt | 25 ++++++++++++------- .../recyclerview/fragment/LookListFragment.kt | 2 +- .../fragment/SceneListFragment.kt | 2 +- .../recyclerview/fragment/ScriptFragment.java | 2 +- .../fragment/SoundListFragment.kt | 2 +- .../fragment/SpriteListFragment.kt | 2 +- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt index 0325e7c531f..5c56cfded79 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt @@ -244,11 +244,6 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att for (i in scenes.indices) { val scene = scenes[i] - if (scene.name.lowercase(Locale.ROOT).contains(query)){ - FinderDataManager.instance.addtoSearchResults(arrayOf(i, i, i, - FinderDataManager.FragmentType.SCENE.id)) - FinderDataManager.instance.addtoSearchResultsNames(scene.name.lowercase(Locale.ROOT)) - } val spriteList = scene.spriteList for (j in spriteList.indices) { val sprite = spriteList[j] @@ -264,11 +259,23 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att } for (order in FinderDataManager.instance.getSearchOrder()){ when (order) { - 2 -> { - if (sprite.name.lowercase(Locale.ROOT).contains(query)){ - FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, j, FinderDataManager.FragmentType.SPRITE.id)) - FinderDataManager.instance.addtoSearchResultsNames(sprite.name.lowercase(Locale.ROOT)) + 1 -> { + if (scene.name.lowercase(Locale.ROOT).contains(query)) { + val exists = FinderDataManager.instance.getSearchResults().any { res -> + res[0] == i && res[1] == i && res[2] == i && + res[3] == FinderDataManager.FragmentType.SCENE.id } + if (!exists) { + FinderDataManager.instance.addtoSearchResults(arrayOf(i, i, i, FinderDataManager.FragmentType.SCENE.id)) + FinderDataManager.instance.addtoSearchResultsNames(scene.name.lowercase(Locale.ROOT)) + } + } + } + 2 -> { + if (sprite.name.lowercase(Locale.ROOT).contains(query)){ + FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, j, FinderDataManager.FragmentType.SPRITE.id)) + FinderDataManager.instance.addtoSearchResultsNames(sprite.name.lowercase(Locale.ROOT)) + } } 3 -> { for (k in bricks.indices) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt index a5736e99882..53410ca361d 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt @@ -65,7 +65,7 @@ class LookListFragment : BaseFinderFragment() { } override fun getSearchOrder(): Array { - return arrayOf(2, 4, 5, 3) + return arrayOf(5,1,2,3,4) } override fun initializeAdapter() { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt index 880b52a342a..ed941c77861 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt @@ -111,7 +111,7 @@ class SceneListFragment : RecyclerViewFragment(), override fun onOpen() { activity.findViewById(R.id.toolbar).visibility = View.GONE finder.setInitiatingFragment(FinderDataManager.FragmentType.SCENE) - val order = arrayOf(2, 3, 4, 5) + val order = arrayOf(1, 2, 3, 4, 5) FinderDataManager.instance.setSearchOrder(order) } }) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index 63cc5b74b80..5337b3bd988 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -359,7 +359,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa finder.setOnOpenListener(() -> { if (FinderDataManager.Companion.getInstance().getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { finder.setInitiatingFragment(FinderDataManager.FragmentType.SCRIPT); - Integer[] order = {2, 3, 4, 5}; + Integer[] order = {3, 4, 5, 1, 2}; FinderDataManager.Companion.getInstance().setSearchOrder(order); } activity.removeTabs(); diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt index 89a8be024c4..78b7ad0d3a3 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt @@ -59,7 +59,7 @@ class SoundListFragment : BaseFinderFragment() { } override fun getSearchOrder(): Array { - return arrayOf(2, 4, 5, 3) + return arrayOf(4, 5, 1, 2, 3) } override fun initializeAdapter() { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt index 13bf85a4ca9..c12b4fbdc9f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt @@ -220,7 +220,7 @@ class SpriteListFragment : RecyclerViewFragment() { override fun onOpen() { activity.findViewById(R.id.toolbar).visibility = View.GONE finder.setInitiatingFragment(FinderDataManager.FragmentType.SPRITE) - val order = arrayOf(2,3,4,5) + val order = arrayOf(2,3,4,5,1) FinderDataManager.instance.setSearchOrder(order) } }) From 195406a099987421f08dccd3f0fbdd9f11318f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tine=20Podlun=C5=A1ek?= Date: Tue, 30 Sep 2025 20:04:34 +0200 Subject: [PATCH 5/5] Review corrections --- .../catrobat/catroid/ui/BaseFinderFragment.kt | 13 +++-- .../java/org/catrobat/catroid/ui/Finder.kt | 49 +++++++++++++++++++ .../catrobat/catroid/ui/FinderDataManager.kt | 11 ++++- .../recyclerview/fragment/LookListFragment.kt | 4 -- .../fragment/SceneListFragment.kt | 6 ++- .../recyclerview/fragment/ScriptFragment.java | 23 ++++++++- .../fragment/SoundListFragment.kt | 7 +-- .../fragment/SpriteListFragment.kt | 12 +++-- 8 files changed, 104 insertions(+), 21 deletions(-) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt index 05dd9fbd93c..b7499d8641d 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/BaseFinderFragment.kt @@ -131,7 +131,7 @@ abstract class BaseFinderFragment : RecyclerViewFragment() { override fun onOpen() { if (FinderDataManager.instance.getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { finder.setInitiatingFragment(getFragmentType()) - FinderDataManager.instance.setSearchOrder(getSearchOrder()) + setInitiatingPosition() } activity.removeTabs() activity.findViewById(R.id.toolbar).visibility = View.GONE @@ -157,5 +157,12 @@ abstract class BaseFinderFragment : RecyclerViewFragment() { } protected abstract fun getFragmentType(): FinderDataManager.FragmentType - protected abstract fun getSearchOrder(): Array -} + fun setInitiatingPosition() { + val sceneIndex = ProjectManager.getInstance().currentProject.sceneList.indexOf(currentScene) + val spriteIndex = ProjectManager.getInstance() + .currentlyEditedScene + .spriteList + .indexOf(ProjectManager.getInstance().currentSprite) + + finder.setInitiatingScene(arrayOf(sceneIndex,spriteIndex,getFragmentType().id)) + }} diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt index 5c56cfded79..dfbb932d07f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/Finder.kt @@ -268,6 +268,15 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att if (!exists) { FinderDataManager.instance.addtoSearchResults(arrayOf(i, i, i, FinderDataManager.FragmentType.SCENE.id)) FinderDataManager.instance.addtoSearchResultsNames(scene.name.lowercase(Locale.ROOT)) + val currentFind = arrayOf(-1, -1, FinderDataManager + .FragmentType.SCENE.id) + if (FinderDataManager.instance.getInitiatingPosition() + .contentEquals(currentFind) && FinderDataManager + .instance.getSearchResultIndex() == -1){ + FinderDataManager.instance.setSearchResultIndex( + (FinderDataManager.instance.getSearchResults().size - + 2)) + } } } } @@ -275,6 +284,15 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att if (sprite.name.lowercase(Locale.ROOT).contains(query)){ FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, j, FinderDataManager.FragmentType.SPRITE.id)) FinderDataManager.instance.addtoSearchResultsNames(sprite.name.lowercase(Locale.ROOT)) + val currentFind = arrayOf(i, -1, FinderDataManager + .FragmentType.SPRITE.id) + if (FinderDataManager.instance.getInitiatingPosition() + .contentEquals(currentFind) && FinderDataManager + .instance.getSearchResultIndex() == -1){ + FinderDataManager.instance.setSearchResultIndex( + (FinderDataManager.instance.getSearchResults().size - + 2)) + } } } 3 -> { @@ -282,6 +300,15 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att val brick = bricks[k] if (searchBrickViews(brick.getView(context), query)) { FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.SCRIPT.id)) + val currentFind = arrayOf(i, j, FinderDataManager + .FragmentType.SCRIPT.id) + if (FinderDataManager.instance.getInitiatingPosition() + .contentEquals(currentFind) && FinderDataManager + .instance.getSearchResultIndex() == -1){ + FinderDataManager.instance.setSearchResultIndex( + (FinderDataManager.instance.getSearchResults() + .size) - 2) + } } } } @@ -292,6 +319,15 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att if (look.name.lowercase(Locale.ROOT).contains(query)) { FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.LOOK.id)) FinderDataManager.instance.addtoSearchResultsNames(look.name.lowercase(Locale.ROOT)) + val currentFind = arrayOf(i, j, FinderDataManager + .FragmentType.LOOK.id) + if (FinderDataManager.instance.getInitiatingPosition() + .contentEquals(currentFind) && FinderDataManager + .instance.getSearchResultIndex() == -1){ + FinderDataManager.instance.setSearchResultIndex( + (FinderDataManager.instance.getSearchResults() + .size) - 2) + } } } } @@ -302,6 +338,15 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att if (sound.name.lowercase(Locale.ROOT).contains(query)) { FinderDataManager.instance.addtoSearchResults(arrayOf(i, j, k, FinderDataManager.FragmentType.SOUND.id)) FinderDataManager.instance.addtoSearchResultsNames(sound.name.lowercase(Locale.ROOT)) + val currentFind = arrayOf(i, j, FinderDataManager + .FragmentType.SOUND.id) + if (FinderDataManager.instance.getInitiatingPosition() + .contentEquals(currentFind) && FinderDataManager + .instance.getSearchResultIndex() == -1){ + FinderDataManager.instance.setSearchResultIndex( + (FinderDataManager.instance.getSearchResults() + .size) - 2) + } } } } @@ -309,6 +354,7 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att } } } + if (!activity.isFinishing) { activity.runOnUiThread { binding.findNext.visibility = VISIBLE @@ -333,6 +379,9 @@ class Finder(context: Context, attrs: AttributeSet?) : LinearLayout(context, att fun setInitiatingFragment(fragmentEnum: FinderDataManager.FragmentType){ FinderDataManager.instance.setInitiatingFragment(fragmentEnum) } + fun setInitiatingScene(InitiatingSceneID: Array){ + FinderDataManager.instance.setInitiatingScene(InitiatingSceneID) + } fun open() { this.visibility = VISIBLE binding.searchBar.isFocusable diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt b/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt index 88a0e779cae..b62f9fd0132 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/FinderDataManager.kt @@ -41,14 +41,23 @@ class FinderDataManager { } private var initiatingfragment:FragmentType = FragmentType.NONE + private var initiatingPosition = arrayOf(-1,-1,-1) private var searchResults = mutableListOf>() private val searchResultsNames = mutableListOf() private var searchResultIndex = -1 private var searchQuery: String? = null - private var searchOrder = arrayOf(-1, -1) + private var searchOrder = arrayOf(1,2,3,4,5) + var startIndex = -1 var currentMatchIndex = -1 var type = -1 + fun getInitiatingPosition(): Array { + return initiatingPosition + } + + fun setInitiatingScene(initiatingSceneID:Array){ + initiatingPosition = initiatingSceneID + } fun getSearchOrder(): Array{ return searchOrder } diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt index 53410ca361d..265227f9921 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/LookListFragment.kt @@ -64,10 +64,6 @@ class LookListFragment : BaseFinderFragment() { return FinderDataManager.FragmentType.LOOK } - override fun getSearchOrder(): Array { - return arrayOf(5,1,2,3,4) - } - override fun initializeAdapter() { sharedPreferenceDetailsKey = SHOW_DETAILS_LOOKS_PREFERENCE_KEY val items = projectManager.currentSprite.lookList diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt index ed941c77861..ba34560eec6 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SceneListFragment.kt @@ -104,6 +104,7 @@ class SceneListFragment : RecyclerViewFragment(), override fun onClose() { activity.findViewById(R.id.toolbar).visibility = View.VISIBLE finishActionMode() + FinderDataManager.instance.setSearchResultIndex(-1) } }) @@ -111,8 +112,9 @@ class SceneListFragment : RecyclerViewFragment(), override fun onOpen() { activity.findViewById(R.id.toolbar).visibility = View.GONE finder.setInitiatingFragment(FinderDataManager.FragmentType.SCENE) - val order = arrayOf(1, 2, 3, 4, 5) - FinderDataManager.instance.setSearchOrder(order) + finder.setInitiatingScene(arrayOf(-1,-1,FinderDataManager + .FragmentType + .SCENE.id)) } }) diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java index 5337b3bd988..6d162bcbdfb 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/ScriptFragment.java @@ -359,8 +359,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa finder.setOnOpenListener(() -> { if (FinderDataManager.Companion.getInstance().getInitiatingFragment() == FinderDataManager.FragmentType.NONE) { finder.setInitiatingFragment(FinderDataManager.FragmentType.SCRIPT); - Integer[] order = {3, 4, 5, 1, 2}; - FinderDataManager.Companion.getInstance().setSearchOrder(order); + setInitiatingPosition(); } activity.removeTabs(); activity.findViewById(R.id.toolbar).setVisibility(View.GONE); @@ -382,6 +381,26 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa return view; } + public void setInitiatingPosition() { + ProjectManager projectManager = ProjectManager.getInstance(); + + int sceneIndex = projectManager.getCurrentProject() + .getSceneList() + .indexOf(projectManager.getCurrentlyEditedScene()); + + int spriteIndex = projectManager.getCurrentlyEditedScene() + .getSpriteList() + .indexOf(projectManager.getCurrentSprite()); + + + Integer[] initiatingPosition = new Integer[]{sceneIndex, spriteIndex, FinderDataManager + .FragmentType + .SCENE.getId()}; + + finder.setInitiatingScene(initiatingPosition); + } + + public String createActionBarTitle(Project currentProject, Scene currentScene, Sprite currentSprite, int flag) { if(flag == 1) { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt index 78b7ad0d3a3..2892a0a2f9f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SoundListFragment.kt @@ -28,6 +28,7 @@ import android.view.Menu import android.view.View import androidx.annotation.PluralsRes import org.catrobat.catroid.BuildConfig +import org.catrobat.catroid.ProjectManager import org.catrobat.catroid.R import org.catrobat.catroid.common.SharedPreferenceKeys import org.catrobat.catroid.common.SoundInfo @@ -55,11 +56,7 @@ class SoundListFragment : BaseFinderFragment() { } override fun getFragmentType(): FinderDataManager.FragmentType { - return FinderDataManager.FragmentType.LOOK - } - - override fun getSearchOrder(): Array { - return arrayOf(4, 5, 1, 2, 3) + return FinderDataManager.FragmentType.SOUND } override fun initializeAdapter() { diff --git a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt index c12b4fbdc9f..139b2a6782f 100644 --- a/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt +++ b/catroid/src/main/java/org/catrobat/catroid/ui/recyclerview/fragment/SpriteListFragment.kt @@ -177,13 +177,13 @@ class SpriteListFragment : RecyclerViewFragment() { totalResults: Int, textView: TextView? ) { + if (FinderDataManager.instance.startIndex != -1){ + } currentProject = ProjectManager.getInstance().currentProject currentScene = currentProject.sceneList[sceneIndex] ProjectManager.getInstance().setCurrentlyEditedScene(currentScene) - makeTitle() - FinderDataManager.instance.currentMatchIndex = brickIndex when (type) { @@ -213,15 +213,19 @@ class SpriteListFragment : RecyclerViewFragment() { override fun onClose() { finishActionMode() activity.findViewById(R.id.toolbar).visibility = View.VISIBLE + FinderDataManager.instance.setSearchResultIndex(-1) } }) finder?.setOnOpenListener(object : Finder.OnOpenListener { override fun onOpen() { + currentProject = ProjectManager.getInstance().currentProject activity.findViewById(R.id.toolbar).visibility = View.GONE finder.setInitiatingFragment(FinderDataManager.FragmentType.SPRITE) - val order = arrayOf(2,3,4,5,1) - FinderDataManager.instance.setSearchOrder(order) + val sceneIndex = ProjectManager.getInstance().currentProject.sceneList.indexOf(currentScene) + finder.setInitiatingScene(arrayOf(sceneIndex,-1,FinderDataManager + .FragmentType + .SPRITE.id)) } }) return parentView