From 96229f4dcd01563385ab8245c1f87c4b96e8560e Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Fri, 7 Oct 2022 23:17:47 +0530 Subject: [PATCH] Use SearchView as an ActionItem in 'Find in file' action --- .../itsaky/androidide/actions/ActionItem.kt | 8 ++ .../internal/DefaultActionsRegistry.kt | 4 + .../editor/find/SearchActionModeAction.kt | 6 ++ .../editor/find/SearchViewActionItem.kt | 82 ++++++++++++++++++ .../androidide/utils/EditorActivityActions.kt | 2 + .../views/editor/SearchActionMode.kt | 33 ++----- tests/test-home/.androidide/init/model.jar | Bin 65240 -> 65240 bytes 7 files changed, 107 insertions(+), 28 deletions(-) create mode 100644 app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchViewActionItem.kt diff --git a/actions/src/main/java/com/itsaky/androidide/actions/ActionItem.kt b/actions/src/main/java/com/itsaky/androidide/actions/ActionItem.kt index 16c0c5a60..92171f428 100644 --- a/actions/src/main/java/com/itsaky/androidide/actions/ActionItem.kt +++ b/actions/src/main/java/com/itsaky/androidide/actions/ActionItem.kt @@ -18,6 +18,7 @@ package com.itsaky.androidide.actions import android.graphics.drawable.Drawable +import android.view.View /** * An action that can be registered using the [ActionsRegistry] @@ -84,6 +85,13 @@ interface ActionItem { enabled = false } + /** + * Create custom action view for this action item. + * + * @return The custom action view or `null`. + */ + fun createActionView(data: ActionData): View? = null + /** Location where an action item will be shown. */ enum class Location(val id: String) { diff --git a/actions/src/main/java/com/itsaky/androidide/actions/internal/DefaultActionsRegistry.kt b/actions/src/main/java/com/itsaky/androidide/actions/internal/DefaultActionsRegistry.kt index 8b9d48519..bc4cee45e 100644 --- a/actions/src/main/java/com/itsaky/androidide/actions/internal/DefaultActionsRegistry.kt +++ b/actions/src/main/java/com/itsaky/androidide/actions/internal/DefaultActionsRegistry.kt @@ -134,6 +134,10 @@ class DefaultActionsRegistry : ActionsRegistry() { if (action.getShowAsActionFlags(data) != -1) { item.setShowAsAction(action.getShowAsActionFlags(data)) } + + action.createActionView(data)?.let { + item.actionView = it + } if (action !is ActionMenu) { item.setOnMenuItemClickListener { diff --git a/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchActionModeAction.kt b/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchActionModeAction.kt index a7b4ea756..3cd966e6a 100644 --- a/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchActionModeAction.kt +++ b/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchActionModeAction.kt @@ -17,6 +17,8 @@ package com.itsaky.androidide.actions.editor.find +import android.view.MenuItem +import com.itsaky.androidide.actions.ActionData import com.itsaky.androidide.actions.ActionItem.Location import com.itsaky.androidide.actions.ActionItem.Location.EDITOR_SEARCH_ACTION_MODE import com.itsaky.androidide.actions.EditorRelatedAction @@ -24,4 +26,8 @@ import com.itsaky.androidide.actions.EditorRelatedAction /** @author Akash Yadav */ abstract class SearchActionModeAction : EditorRelatedAction() { override var location: Location = EDITOR_SEARCH_ACTION_MODE + + override fun getShowAsActionFlags(data: ActionData): Int { + return MenuItem.SHOW_AS_ACTION_IF_ROOM + } } diff --git a/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchViewActionItem.kt b/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchViewActionItem.kt new file mode 100644 index 000000000..c816c6e72 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/actions/editor/find/SearchViewActionItem.kt @@ -0,0 +1,82 @@ +/* + * This file is part of AndroidIDE. + * + * AndroidIDE is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * AndroidIDE 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with AndroidIDE. If not, see . + */ + +package com.itsaky.androidide.actions.editor.find + +import android.app.SearchManager +import android.content.Context +import android.text.TextUtils +import android.view.MenuItem +import android.view.View +import androidx.appcompat.widget.SearchView +import androidx.core.content.ContextCompat +import com.itsaky.androidide.R +import com.itsaky.androidide.actions.ActionData +import com.itsaky.androidide.app.IDEActivity +import com.itsaky.androidide.views.editor.IDEEditor +import io.github.rosemoe.sora.widget.EditorSearcher.SearchOptions + +/** + * The [SearchView] action in the search action mode. + * + * @author Akash Yadav + */ +class SearchViewActionItem() : SearchActionModeAction() { + override val id: String = "editor.search.view" + + constructor(context: Context) : this() { + label = context.getString(R.string.text_to_search) + icon = ContextCompat.getDrawable(context, R.drawable.ic_search) + } + + override fun execAction(data: ActionData): Any { + return Unit + } + + override fun createActionView(data: ActionData): View? { + val editor = getEditor(data) ?: return null + val searchManager = editor.context.getSystemService(Context.SEARCH_SERVICE) as SearchManager + + val search = SearchView(editor.context) + search.isIconified = false + search.queryHint = editor.context.getString(R.string.text_to_search) + search.setSearchableInfo( + searchManager.getSearchableInfo((editor.context as IDEActivity).componentName) + ) + search.setOnQueryTextListener(OnQueryListener(editor)) + search.performClick() + search.setIconifiedByDefault(false) + return search + } + + private class OnQueryListener(val editor: IDEEditor) : SearchView.OnQueryTextListener { + override fun onQueryTextSubmit(query: String?): Boolean { + editor.searcher.gotoNext() + return false + } + + override fun onQueryTextChange(newText: String?): Boolean { + if (TextUtils.isEmpty(newText)) { + editor.searcher.stopSearch() + return false + } + + editor.searcher.search(newText!!, SearchOptions(false, false)) + return false + } + } +} diff --git a/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt b/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt index b9f1cb0d6..448f4f942 100644 --- a/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt +++ b/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt @@ -31,6 +31,7 @@ import com.itsaky.androidide.actions.editor.SelectAllAction import com.itsaky.androidide.actions.editor.find.GoToNextAction import com.itsaky.androidide.actions.editor.find.GoToPreviousAction import com.itsaky.androidide.actions.editor.find.ReplaceAction +import com.itsaky.androidide.actions.editor.find.SearchViewActionItem import com.itsaky.androidide.actions.etc.DaemonStatusAction import com.itsaky.androidide.actions.etc.FileTreeAction import com.itsaky.androidide.actions.etc.FindActionMenu @@ -73,6 +74,7 @@ class EditorActivityActions { registry.registerAction(FormatCodeAction(context)) // editor search actions + registry.registerAction(SearchViewActionItem(context)) registry.registerAction(GoToNextAction(context)) registry.registerAction(GoToPreviousAction(context)) registry.registerAction(ReplaceAction(context)) diff --git a/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt b/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt index 42111952a..68463e1ac 100644 --- a/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt +++ b/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt @@ -18,16 +18,20 @@ package com.itsaky.androidide.views.editor import android.annotation.SuppressLint +import android.app.SearchManager import android.content.Context import android.text.TextUtils import android.view.ActionMode import android.view.Menu import android.view.MenuItem +import android.view.ViewGroup.LayoutParams +import android.view.ViewGroup.LayoutParams.MATCH_PARENT import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.SearchView import com.itsaky.androidide.actions.ActionData import com.itsaky.androidide.actions.ActionItem import com.itsaky.androidide.actions.ActionsRegistry +import com.itsaky.androidide.app.IDEActivity import io.github.rosemoe.sora.R import io.github.rosemoe.sora.widget.CodeEditor import io.github.rosemoe.sora.widget.EditorSearcher.SearchOptions @@ -37,25 +41,15 @@ import io.github.rosemoe.sora.widget.EditorSearcher.SearchOptions * @author Akash Yadav */ class SearchActionMode(val editor: IDEEditor) : ActionMode.Callback { - + @SuppressLint("RestrictedApi") override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { - if (mode == null) { return false } - if (menu is MenuBuilder) { menu.setOptionalIconsVisible(true) } - - val search = SearchView(editor.context) - search.setOnQueryTextListener(OnQueryListener(editor)) - search.isIconified = false - search.queryHint = editor.context.getString(R.string.text_to_search) - search.performClick() - search.setIconifiedByDefault(false) - mode.customView = search return true } @@ -87,21 +81,4 @@ class SearchActionMode(val editor: IDEEditor) : ActionMode.Callback { put(ActionMode::class.java, mode) } } - - private class OnQueryListener(val editor: IDEEditor) : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(query: String?): Boolean { - editor.searcher.gotoNext() - return false - } - - override fun onQueryTextChange(newText: String?): Boolean { - if (TextUtils.isEmpty(newText)) { - editor.searcher.stopSearch() - return false - } - - editor.searcher.search(newText!!, SearchOptions(false, false)) - return false - } - } } diff --git a/tests/test-home/.androidide/init/model.jar b/tests/test-home/.androidide/init/model.jar index 0ed621675a06ee634c532c95d158ed0443ff42a0..3dec90c7b005dea1d4d82fc194f9813fd8330f2f 100644 GIT binary patch delta 31 ncmccdm-)tDW}X0VW)?061`ZB}A3HblSiWcav2(Ng`-%Jjy4?&* delta 31 ncmccdm-)tDW}X0VW)?061`ZAefrO1bmhYJa5;nWPpU4jYp*ji4