mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Dynamically add toolbar actions using ActionsRegistry
This commit is contained in:
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KtfmtSettings">
|
||||
<option name="enabled" value="true" />
|
||||
<option name="uiFormatterStyle" value="Dropbox" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+4
@@ -30,11 +30,14 @@
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_copy.xml" value="0.188" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_github.xml" value="0.21837606837606838" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_linear_layout.xml" value="0.175" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_lint.xml" value="0.151" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_min_sdk.xml" value="0.147" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_password_input.xml" value="0.147" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_pick_color.xml" value="0.147" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_quickfix.xml" value="0.14" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_relative_layout.xml" value="0.175" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_run.xml" value="0.151" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_run_debug.xml" value="0.151" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_save.xml" value="0.26205128205128203" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_signature_help.xml" value="0.19907407407407407" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_text_actions.xml" value="0.147" />
|
||||
@@ -127,6 +130,7 @@
|
||||
<entry key="..\:/Users/Akash Yadav/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_create_project_content.xml" value="0.33" />
|
||||
<entry key="..\:/Users/Akash Yadav/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_widget_item.xml" value="0.264" />
|
||||
<entry key="..\:/Users/Akash Yadav/AndroidStudioProjects/android-ide/app/src/main/res/menu/menu_designer_widgets.xml" value="0.20854700854700856" />
|
||||
<entry key="..\:/itsaky/.gradle/caches/transforms-3/e4862cae80f8754ca1a451ad3e00b14c/transformed/jetified-editor-0.10.11/res/drawable/round_select_all_20.xml" value="0.1305" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,37 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdk
|
||||
buildToolsVersion rootProject.ext.buildTools
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdk
|
||||
targetSdkVersion rootProject.ext.targetSdk
|
||||
}
|
||||
|
||||
buildFeatures.viewBinding true
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility rootProject.ext.javaSourceVersion
|
||||
targetCompatibility rootProject.ext.javaTargetVersion
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':common')
|
||||
implementation common.editor
|
||||
implementation common.utilcode
|
||||
|
||||
implementation "androidx.core:core-ktx:1.7.0"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext () {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation ().getTargetContext ();
|
||||
assertEquals ("com.itsaky.androidide.actions.test", appContext.getPackageName ());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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 <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<manifest package="com.itsaky.androidide.actions" />
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class ActionData {
|
||||
|
||||
private final Map<Class<?>, Object> instances = new HashMap<>();
|
||||
|
||||
public <T> void put(@NonNull Class<T> type, @Nullable T object) {
|
||||
Objects.requireNonNull(type);
|
||||
this.instances.put(type, object);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T> T get(@NonNull Class<T> type) {
|
||||
Objects.requireNonNull(type);
|
||||
|
||||
final var object = this.instances.get(type);
|
||||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return type.cast(object);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.instances.clear();
|
||||
}
|
||||
}
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
|
||||
/**
|
||||
* An action that can be registered using the [ActionsRegistry]
|
||||
* [com.itsaky.androidide.actions.ActionsRegistry]
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
interface ActionItem {
|
||||
|
||||
val id: String
|
||||
var label: String
|
||||
var visible: Boolean
|
||||
var enabled: Boolean
|
||||
var icon: Drawable?
|
||||
var requiresUIThread: Boolean
|
||||
var location: Location
|
||||
|
||||
/**
|
||||
* Prepare the action. Subclasses can modify the visual properties of this action here.
|
||||
* @param data The data containing various information about the event.
|
||||
*/
|
||||
fun prepare(data: ActionData)
|
||||
|
||||
/**
|
||||
* Execute the action. The action executed in a background thread by default.
|
||||
*
|
||||
* @param data The data containing various information about the event.
|
||||
* @return `true` if this action was executed successfully, `false` otherwise.
|
||||
*/
|
||||
fun execAction(data: ActionData): Boolean
|
||||
|
||||
/**
|
||||
* Called just after the [execAction] method executes **successfully** (i.e. returns `true`).
|
||||
* Subclasses are free to do UI related work here as this method is called on UI thread.
|
||||
*
|
||||
* @param data The data containing various information about the event.
|
||||
*/
|
||||
fun postExec(data: ActionData, execResult: Boolean) {}
|
||||
|
||||
/** Location where an action item will be shown. */
|
||||
enum class Location(val id: String) {
|
||||
|
||||
/** Location marker for action items shown in editor activity's toolbar. */
|
||||
EDITOR_TOOLBAR("editor_toolbar"),
|
||||
|
||||
/** Location marker for action items shown in editor's text action menu. */
|
||||
EDITOR_TEXT_ACTIONS("editor_text_actions"),
|
||||
|
||||
/**
|
||||
* Location marker for action items shown in 'Code actions' submenu in editor's text action
|
||||
* menu.
|
||||
*/
|
||||
EDITOR_CODE_ACTIONS("editor_code_actions");
|
||||
|
||||
override fun toString(): String {
|
||||
return id
|
||||
}
|
||||
|
||||
fun forId(id: String): Location {
|
||||
return values().first { it.id == id }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
/**
|
||||
* An action menu is an action which can contain child actions.
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
interface ActionMenu : ActionItem {
|
||||
|
||||
val children: MutableSet<ActionItem>
|
||||
|
||||
fun addAction(action: ActionItem) = children.add(action)
|
||||
|
||||
fun removeAction(action: ActionItem) = children.remove(action)
|
||||
|
||||
/** Action menus are not supposed to perform any action */
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
import android.view.Menu
|
||||
import com.itsaky.androidide.actions.internal.DefaultActionsRegistry
|
||||
|
||||
/** @author Akash Yadav */
|
||||
abstract class ActionsRegistry {
|
||||
|
||||
companion object {
|
||||
|
||||
private var instance: ActionsRegistry? = null
|
||||
|
||||
@JvmStatic
|
||||
fun getInstance(): ActionsRegistry {
|
||||
if (instance == null) {
|
||||
instance = DefaultActionsRegistry()
|
||||
}
|
||||
|
||||
return instance as ActionsRegistry
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given action.
|
||||
*
|
||||
* @param action The action to register. Must not be `null`.
|
||||
* @return `true` if the action was registered successfully. `false` otherwise.
|
||||
*/
|
||||
abstract fun registerAction(action: ActionItem): Boolean
|
||||
|
||||
/**
|
||||
* Unregister the given action.
|
||||
*
|
||||
* @param action The action to unregister. Must not be `null`.
|
||||
* @return `true` if the action was unregistered successfully. `false` otherwise.
|
||||
*/
|
||||
abstract fun unregisterAction(action: ActionItem): Boolean
|
||||
|
||||
/**
|
||||
* Unregister the action with the given ID.
|
||||
*
|
||||
* @param id The ID of action to unregister. Must not be `null`.
|
||||
* @return `true` if the action was unregistered successfully. `false` otherwise.
|
||||
*/
|
||||
abstract fun unregisterAction(id: String): Boolean
|
||||
|
||||
/**
|
||||
* Find the action with the given ID.
|
||||
*
|
||||
* @param id The ID of the action to find.
|
||||
* @return The found action or `null`.
|
||||
*/
|
||||
abstract fun findAction(location: ActionItem.Location, id: String): ActionItem?
|
||||
|
||||
/**
|
||||
* Fill the given menu with the registered actions.
|
||||
*
|
||||
* Subclasses must first call [ActionItem.prepare] to update the action.
|
||||
*/
|
||||
abstract fun fillMenu(data: ActionData, location: ActionItem.Location, menu: Menu)
|
||||
|
||||
/** Clear all the registered actions. */
|
||||
abstract fun clearActions(location: ActionItem.Location)
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.itsaky.androidide.actions.internal
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.ActionItem
|
||||
import com.itsaky.androidide.actions.ActionMenu
|
||||
import com.itsaky.androidide.actions.ActionsRegistry
|
||||
import com.itsaky.androidide.utils.Logger
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
* Default implementation for the [ActionsRegistry]
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class DefaultActionsRegistry : ActionsRegistry() {
|
||||
|
||||
private val log = Logger.newInstance("DefaultActionsRegistry")
|
||||
private val actions: MutableMap<String, MutableMap<String, ActionItem>> = mutableMapOf()
|
||||
|
||||
private fun getActions(location: ActionItem.Location): MutableMap<String, ActionItem> {
|
||||
if (actions[location.id] == null) {
|
||||
actions[location.id] = mutableMapOf()
|
||||
}
|
||||
|
||||
return actions[location.id]!!
|
||||
}
|
||||
|
||||
override fun registerAction(action: ActionItem): Boolean {
|
||||
val actionsAtLocation = getActions(action.location)
|
||||
actionsAtLocation[action.id] = action
|
||||
return true
|
||||
}
|
||||
|
||||
override fun unregisterAction(action: ActionItem): Boolean {
|
||||
val actions = getActions(action.location)
|
||||
val older = actions.remove(action.id)
|
||||
if (older != null) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun unregisterAction(id: String): Boolean {
|
||||
for (locations in this.actions.values) {
|
||||
val older = locations.remove(id)
|
||||
if (older != null) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun findAction(location: ActionItem.Location, id: String): ActionItem? =
|
||||
getActions(location)[id]
|
||||
|
||||
override fun clearActions(location: ActionItem.Location) = getActions(location).clear()
|
||||
|
||||
override fun fillMenu(data: ActionData, location: ActionItem.Location, menu: Menu) {
|
||||
val actions = getActions(location)
|
||||
|
||||
for (action in actions.values) {
|
||||
action.prepare(data)
|
||||
|
||||
if (!action.visible) {
|
||||
continue
|
||||
}
|
||||
addActionToMenu(menu, action, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addActionToMenu(menu: Menu, action: ActionItem, data: ActionData) {
|
||||
val item: MenuItem =
|
||||
if (action is ActionMenu) {
|
||||
val sub = menu.addSubMenu(action.label)
|
||||
|
||||
for (subItem in action.children) {
|
||||
subItem.prepare(data)
|
||||
if (subItem.visible) {
|
||||
addActionToMenu(sub, subItem, data)
|
||||
}
|
||||
}
|
||||
|
||||
sub.item
|
||||
} else {
|
||||
menu.add(action.label)
|
||||
}
|
||||
|
||||
item.isEnabled = action.enabled
|
||||
item.icon = action.icon
|
||||
|
||||
if (item.icon != null) {
|
||||
item.icon.alpha = if (action.enabled) 255 else 76
|
||||
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
} else {
|
||||
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
|
||||
}
|
||||
|
||||
if (action !is ActionMenu) {
|
||||
item.setOnMenuItemClickListener {
|
||||
if (action.requiresUIThread) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
val result = action.execAction(data)
|
||||
action.postExec(data, result)
|
||||
}
|
||||
} else {
|
||||
execInBackground(action, data, it)
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun execInBackground(action: ActionItem, data: ActionData, it: MenuItem) {
|
||||
val start = System.currentTimeMillis()
|
||||
CompletableFuture.supplyAsync { action.execAction(data) }.whenComplete { result, error ->
|
||||
if (result == null || !result || error != null) {
|
||||
log.error(
|
||||
"An error occurred when performing action '${it.title}'. Action failed in ${System.currentTimeMillis() - start}ms",
|
||||
error)
|
||||
} else {
|
||||
log.info(
|
||||
"Action '${it.title}' completed in ${System.currentTimeMillis() - start}ms")
|
||||
}
|
||||
|
||||
ThreadUtils.runOnUiThread { action.postExec(data, result ?: false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect () {
|
||||
assertEquals (4, 2 + 2);
|
||||
}
|
||||
}
|
||||
@@ -122,6 +122,7 @@ dependencies {
|
||||
implementation project(':xml-inflater')
|
||||
implementation project(':lexers')
|
||||
implementation project(':common')
|
||||
implementation project(':actions')
|
||||
|
||||
implementation project(':lsp:api')
|
||||
implementation project(':lsp:java')
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.itsaky.androidide;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
@@ -58,6 +59,7 @@ import com.blankj.utilcode.util.IntentUtils;
|
||||
import com.blankj.utilcode.util.KeyboardUtils;
|
||||
import com.blankj.utilcode.util.ResourceUtils;
|
||||
import com.blankj.utilcode.util.SizeUtils;
|
||||
import com.blankj.utilcode.util.ThreadUtils;
|
||||
import com.blankj.utilcode.util.ThrowableUtils;
|
||||
import com.blankj.utilcode.util.ZipUtils;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
@@ -65,6 +67,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.navigation.NavigationView;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.google.android.material.tabs.TabLayoutMediator;
|
||||
import com.itsaky.androidide.actions.ActionData;
|
||||
import com.itsaky.androidide.actions.ActionsRegistry;
|
||||
import com.itsaky.androidide.adapters.DiagnosticsAdapter;
|
||||
import com.itsaky.androidide.adapters.EditorBottomSheetTabAdapter;
|
||||
import com.itsaky.androidide.adapters.SearchListAdapter;
|
||||
@@ -79,6 +83,7 @@ import com.itsaky.androidide.fragments.sheets.OptionsListFragment;
|
||||
import com.itsaky.androidide.fragments.sheets.ProgressSheet;
|
||||
import com.itsaky.androidide.fragments.sheets.TextSheetFragment;
|
||||
import com.itsaky.androidide.handlers.BuildServiceHandler;
|
||||
import com.itsaky.androidide.handlers.EditorActivityActions;
|
||||
import com.itsaky.androidide.handlers.FileOptionsHandler;
|
||||
import com.itsaky.androidide.handlers.IDEHandler;
|
||||
import com.itsaky.androidide.interfaces.DiagnosticClickListener;
|
||||
@@ -154,24 +159,6 @@ public class EditorActivity extends StudioActivity
|
||||
private static final int ACTION_ID_OTHERS = 101;
|
||||
private static final int ACTION_ID_ALL = 102;
|
||||
private static final Logger LOG = Logger.newInstance("EditorActivity");
|
||||
/**
|
||||
* MenuItem(s) that are related to the build process
|
||||
*
|
||||
* <p>These items will be disabled once the build process starts and will be enabled after the
|
||||
* execution
|
||||
*/
|
||||
private final int[] BUILD_IDS = {
|
||||
R.id.menuEditor_quickRun,
|
||||
R.id.menuEditor_runDebug,
|
||||
R.id.menuEditor_runRelease,
|
||||
R.id.menuEditor_runBuild,
|
||||
R.id.menuEditor_runBundle,
|
||||
R.id.menuEditor_runClean,
|
||||
R.id.menuEditor_runCleanBuild,
|
||||
R.id.menuEditor_lint,
|
||||
R.id.menuEditor_lintDebug,
|
||||
R.id.menuEditor_lintRelease
|
||||
};
|
||||
|
||||
private ActivityEditorBinding mBinding;
|
||||
private LayoutDiagnosticInfoBinding mDiagnosticInfoBinding;
|
||||
@@ -234,6 +221,9 @@ public class EditorActivity extends StudioActivity
|
||||
registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
this::onGetUIDesignerResult);
|
||||
|
||||
EditorActivityActions.register(this);
|
||||
ensureToolbarMenu();
|
||||
}
|
||||
|
||||
private void setupDrawerToggle() {
|
||||
@@ -354,14 +344,18 @@ public class EditorActivity extends StudioActivity
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
dispatchOnPauseToEditors();
|
||||
super.onPause();
|
||||
dispatchOnPauseToEditors();
|
||||
EditorActivityActions.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
EditorActivityActions.register(this);
|
||||
ensureToolbarMenu();
|
||||
|
||||
try {
|
||||
checkForCompilerModule();
|
||||
dispatchOnResumeToEditors();
|
||||
@@ -383,88 +377,90 @@ public class EditorActivity extends StudioActivity
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("AlwaysShowAction")
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
for (int id : BUILD_IDS) {
|
||||
MenuItem item = menu.findItem(id);
|
||||
if (item != null) {
|
||||
boolean enabled = getBuildService() != null && !getBuildService().isBuilding();
|
||||
item.setEnabled(enabled);
|
||||
item.getIcon().setAlpha(enabled ? 255 : 76);
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem run1 = menu.findItem(R.id.menuEditor_quickRun);
|
||||
MenuItem run2 = menu.findItem(R.id.menuEditor_run);
|
||||
MenuItem undo = menu.findItem(R.id.menuEditor_undo);
|
||||
MenuItem redo = menu.findItem(R.id.menuEditor_redo);
|
||||
MenuItem save = menu.findItem(R.id.menuEditor_save);
|
||||
MenuItem def = menu.findItem(R.id.menuEditor_gotoDefinition);
|
||||
MenuItem ref = menu.findItem(R.id.menuEditor_findReferences);
|
||||
MenuItem comment = menu.findItem(R.id.menuEditor_commentLine);
|
||||
MenuItem uncomment = menu.findItem(R.id.menuEditor_uncommentLine);
|
||||
MenuItem findFile = menu.findItem(R.id.menuEditor_findFile);
|
||||
MenuItem viewLayout = menu.findItem(R.id.menuEditor_viewLayout);
|
||||
|
||||
if (KeyboardUtils.isSoftInputVisible(this)) {
|
||||
run1.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
run2.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
undo.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
redo.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
|
||||
viewLayout.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
} else {
|
||||
run1.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
run2.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
undo.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
redo.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
|
||||
viewLayout.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
|
||||
final var editor = getCurrentEditor();
|
||||
final var file = editor != null ? editor.getFile() : null;
|
||||
final var notNull = editor != null && file != null;
|
||||
final var isJava = notNull && file.getName().endsWith(".java");
|
||||
final var isXml = notNull && file.getName().endsWith(".xml");
|
||||
final var filesModified = notNull && mViewModel != null && mViewModel.areFilesModified();
|
||||
final var isLayout =
|
||||
isXml
|
||||
&& file.getParentFile() != null
|
||||
&& Pattern.compile(FileOptionsHandler.LAYOUT_RES_PATH_REGEX)
|
||||
.matcher(file.getParentFile().getAbsolutePath())
|
||||
.matches();
|
||||
final var nullableAlpha = notNull ? 255 : 76;
|
||||
final var javaFileAlpha = isJava ? 255 : 76;
|
||||
final var layoutFileAlpha = isLayout ? 255 : 76;
|
||||
final var saveAlpha = filesModified ? 255 : 76;
|
||||
|
||||
undo.setEnabled(notNull);
|
||||
redo.setEnabled(notNull);
|
||||
save.setEnabled(filesModified);
|
||||
comment.setEnabled(notNull);
|
||||
uncomment.setEnabled(notNull);
|
||||
findFile.setEnabled(notNull);
|
||||
def.setEnabled(isJava);
|
||||
ref.setEnabled(isJava);
|
||||
|
||||
undo.getIcon().setAlpha(nullableAlpha);
|
||||
redo.getIcon().setAlpha(nullableAlpha);
|
||||
save.getIcon().setAlpha(saveAlpha);
|
||||
comment.getIcon().setAlpha(nullableAlpha);
|
||||
uncomment.getIcon().setAlpha(nullableAlpha);
|
||||
findFile.getIcon().setAlpha(nullableAlpha);
|
||||
def.getIcon().setAlpha(javaFileAlpha);
|
||||
ref.getIcon().setAlpha(javaFileAlpha);
|
||||
|
||||
viewLayout.setEnabled(isLayout);
|
||||
viewLayout.getIcon().setAlpha(layoutFileAlpha);
|
||||
viewLayout.setShowAsActionFlags(
|
||||
isLayout ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
|
||||
return true;
|
||||
}
|
||||
// @Override
|
||||
// @SuppressLint("AlwaysShowAction")
|
||||
// public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
// for (int id : BUILD_IDS) {
|
||||
// MenuItem item = menu.findItem(id);
|
||||
// if (item != null) {
|
||||
// boolean enabled = getBuildService() != null &&
|
||||
// !getBuildService().isBuilding();
|
||||
// item.setEnabled(enabled);
|
||||
// item.getIcon().setAlpha(enabled ? 255 : 76);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// MenuItem run1 = menu.findItem(R.id.menuEditor_quickRun);
|
||||
// MenuItem run2 = menu.findItem(R.id.menuEditor_run);
|
||||
// MenuItem undo = menu.findItem(R.id.menuEditor_undo);
|
||||
// MenuItem redo = menu.findItem(R.id.menuEditor_redo);
|
||||
// MenuItem save = menu.findItem(R.id.menuEditor_save);
|
||||
// MenuItem def = menu.findItem(R.id.menuEditor_gotoDefinition);
|
||||
// MenuItem ref = menu.findItem(R.id.menuEditor_findReferences);
|
||||
// MenuItem comment = menu.findItem(R.id.menuEditor_commentLine);
|
||||
// MenuItem uncomment = menu.findItem(R.id.menuEditor_uncommentLine);
|
||||
// MenuItem findFile = menu.findItem(R.id.menuEditor_findFile);
|
||||
// MenuItem viewLayout = menu.findItem(R.id.menuEditor_viewLayout);
|
||||
//
|
||||
// if (KeyboardUtils.isSoftInputVisible(this)) {
|
||||
// run1.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
// run2.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
// undo.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
// redo.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
//
|
||||
// viewLayout.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
// } else {
|
||||
// run1.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
// run2.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
// undo.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
// redo.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
//
|
||||
// viewLayout.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
// }
|
||||
//
|
||||
// final var editor = getCurrentEditor();
|
||||
// final var file = editor != null ? editor.getFile() : null;
|
||||
// final var notNull = editor != null && file != null;
|
||||
// final var isJava = notNull && file.getName().endsWith(".java");
|
||||
// final var isXml = notNull && file.getName().endsWith(".xml");
|
||||
// final var filesModified = notNull && mViewModel != null &&
|
||||
// mViewModel.areFilesModified();
|
||||
// final var isLayout =
|
||||
// isXml
|
||||
// && file.getParentFile() != null
|
||||
// && Pattern.compile(FileOptionsHandler.LAYOUT_RES_PATH_REGEX)
|
||||
// .matcher(file.getParentFile().getAbsolutePath())
|
||||
// .matches();
|
||||
// final var nullableAlpha = notNull ? 255 : 76;
|
||||
// final var javaFileAlpha = isJava ? 255 : 76;
|
||||
// final var layoutFileAlpha = isLayout ? 255 : 76;
|
||||
// final var saveAlpha = filesModified ? 255 : 76;
|
||||
//
|
||||
// undo.setEnabled(notNull);
|
||||
// redo.setEnabled(notNull);
|
||||
// save.setEnabled(filesModified);
|
||||
// comment.setEnabled(notNull);
|
||||
// uncomment.setEnabled(notNull);
|
||||
// findFile.setEnabled(notNull);
|
||||
// def.setEnabled(isJava);
|
||||
// ref.setEnabled(isJava);
|
||||
//
|
||||
// undo.getIcon().setAlpha(nullableAlpha);
|
||||
// redo.getIcon().setAlpha(nullableAlpha);
|
||||
// save.getIcon().setAlpha(saveAlpha);
|
||||
// comment.getIcon().setAlpha(nullableAlpha);
|
||||
// uncomment.getIcon().setAlpha(nullableAlpha);
|
||||
// findFile.getIcon().setAlpha(nullableAlpha);
|
||||
// def.getIcon().setAlpha(javaFileAlpha);
|
||||
// ref.getIcon().setAlpha(javaFileAlpha);
|
||||
//
|
||||
// viewLayout.setEnabled(isLayout);
|
||||
// viewLayout.getIcon().setAlpha(layoutFileAlpha);
|
||||
// viewLayout.setShowAsActionFlags(
|
||||
// isLayout ? MenuItem.SHOW_AS_ACTION_ALWAYS : MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
@SuppressLint("RestrictedApi")
|
||||
@Override
|
||||
@@ -474,77 +470,21 @@ public class EditorActivity extends StudioActivity
|
||||
builder.setOptionalIconsVisible(true);
|
||||
}
|
||||
|
||||
getMenuInflater().inflate(R.menu.menu_editor, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (getBuildService() == null) {
|
||||
LOG.error("Build service is null. Cannot perform option menu actions.");
|
||||
return false;
|
||||
}
|
||||
public void ensureToolbarMenu() {
|
||||
final var menu = mBinding.editorToolbar.getMenu();
|
||||
menu.clear();
|
||||
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.menuEditor_runDebug || id == R.id.menuEditor_quickRun) {
|
||||
getBuildServiceHandler().assembleDebug(true);
|
||||
} else if (id == R.id.menuEditor_runRelease) {
|
||||
getBuildService().assembleRelease();
|
||||
} else if (id == R.id.menuEditor_runClean) {
|
||||
getBuildService().clean();
|
||||
} else if (id == R.id.menuEditor_runCleanBuild) {
|
||||
getBuildService().cleanAndRebuild();
|
||||
} else if (id == R.id.menuEditor_runStopDaemons) {
|
||||
getBuildService().stopAllDaemons();
|
||||
} else if (id == R.id.menuEditor_runBuild) {
|
||||
getBuildService().build();
|
||||
} else if (id == R.id.menuEditor_runBundle) {
|
||||
getBuildService().bundle();
|
||||
} else if (id == R.id.menuEditor_lint) {
|
||||
getBuildService().lint();
|
||||
} else if (id == R.id.menuEditor_lintDebug) {
|
||||
getBuildService().lintDebug();
|
||||
} else if (id == R.id.menuEditor_lintRelease) {
|
||||
getBuildService().lintRelease();
|
||||
} else if (id == R.id.menuEditor_save) {
|
||||
saveAll(true, true);
|
||||
} else if (id == R.id.menuEditor_findProject) {
|
||||
AlertDialog d = getFindInProjectDialog();
|
||||
if (d != null) {
|
||||
d.show();
|
||||
}
|
||||
} else if (id == R.id.menuEditor_viewLayout) {
|
||||
previewLayout();
|
||||
} else if (id == R.id.menuEditor_daemonStatus) {
|
||||
showDaemonStatus();
|
||||
} else if (id == R.id.menuEditor_files) {
|
||||
if (!mBinding.editorDrawerLayout.isDrawerOpen(GravityCompat.END)) {
|
||||
mBinding.editorDrawerLayout.openDrawer(GravityCompat.END);
|
||||
}
|
||||
} else if (getCurrentEditor() != null) { // Should be checked at last
|
||||
if (id == R.id.menuEditor_undo) {
|
||||
this.getCurrentEditor().undo();
|
||||
} else if (id == R.id.menuEditor_redo) {
|
||||
this.getCurrentEditor().redo();
|
||||
} else if (id == R.id.menuEditor_gotoDefinition) {
|
||||
this.getCurrentEditor().findDefinition();
|
||||
} else if (id == R.id.menuEditor_findReferences) {
|
||||
this.getCurrentEditor().findReferences();
|
||||
} else if (id == R.id.menuEditor_commentLine) {
|
||||
this.getCurrentEditor().commentLine();
|
||||
} else if (id == R.id.menuEditor_uncommentLine) {
|
||||
this.getCurrentEditor().uncommentLine();
|
||||
} else if (id == R.id.menuEditor_findFile) {
|
||||
this.getCurrentEditor().beginSearch();
|
||||
} else if (id == R.id.menuEditor_formatCode) {
|
||||
if (!this.getCurrentEditor().getEditor().formatCodeAsync()) {
|
||||
LOG.error("Unable to start format thread to format code...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invalidateOptionsMenu();
|
||||
return true;
|
||||
final var data = new ActionData();
|
||||
data.put(Context.class, EditorActivity.this);
|
||||
data.put(CodeEditorView.class, getCurrentEditor());
|
||||
ActionsRegistry.getInstance()
|
||||
.fillMenu(
|
||||
data,
|
||||
com.itsaky.androidide.actions.ActionItem.Location.EDITOR_TOOLBAR,
|
||||
menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -728,7 +668,7 @@ public class EditorActivity extends StudioActivity
|
||||
editorView.onEditorSelected();
|
||||
mViewModel.setCurrentFile(position, editorView.getFile());
|
||||
refreshSymbolInput(editorView);
|
||||
invalidateOptionsMenu();
|
||||
ensureToolbarMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -741,6 +681,10 @@ public class EditorActivity extends StudioActivity
|
||||
editor.ensureWindowsDismissed();
|
||||
}
|
||||
}
|
||||
|
||||
if (mViewModel.getOpenedFileCount() <= 0) {
|
||||
ensureToolbarMenu();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -928,7 +872,8 @@ public class EditorActivity extends StudioActivity
|
||||
modified = modified || editor.isModified();
|
||||
}
|
||||
|
||||
mViewModel.setFilesModified(modified);
|
||||
final boolean finalModified = modified;
|
||||
ThreadUtils.runOnUiThread(() -> mViewModel.setFilesModified(finalModified));
|
||||
}
|
||||
|
||||
public void install(@NonNull File apk) {
|
||||
@@ -984,7 +929,7 @@ public class EditorActivity extends StudioActivity
|
||||
|
||||
mBinding.editorContainer.setDisplayedChild(index);
|
||||
|
||||
invalidateOptionsMenu();
|
||||
ensureToolbarMenu();
|
||||
try {
|
||||
return getEditorAtIndex(index);
|
||||
} catch (Throwable th) {
|
||||
@@ -1049,7 +994,7 @@ public class EditorActivity extends StudioActivity
|
||||
}
|
||||
|
||||
mBinding.tabs.requestLayout();
|
||||
invalidateOptionsMenu();
|
||||
ensureToolbarMenu();
|
||||
}
|
||||
|
||||
public void closeAll() {
|
||||
@@ -1086,7 +1031,7 @@ public class EditorActivity extends StudioActivity
|
||||
mBinding.tabs.requestLayout();
|
||||
mBinding.editorContainer.removeAllViews();
|
||||
|
||||
invalidateOptionsMenu();
|
||||
ensureToolbarMenu();
|
||||
|
||||
if (onSaved != null) {
|
||||
onSaved.run();
|
||||
@@ -1097,6 +1042,14 @@ public class EditorActivity extends StudioActivity
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areFilesModified() {
|
||||
return mViewModel.areFilesModified();
|
||||
}
|
||||
|
||||
public EditorViewModel getViewModel() {
|
||||
return mViewModel;
|
||||
}
|
||||
|
||||
private void notifyFilesUnsaved(List<CodeEditorView> unsavedEditors, Runnable invokeAfter) {
|
||||
//noinspection ConstantConditions
|
||||
final var mapped =
|
||||
@@ -1198,6 +1151,29 @@ public class EditorActivity extends StudioActivity
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void previewLayout() {
|
||||
try {
|
||||
|
||||
if (getCurrentEditor() == null || getCurrentEditor().getFile() == null) {
|
||||
LOG.error("No file is opened. Cannot preview layout.");
|
||||
return;
|
||||
}
|
||||
|
||||
saveAll(false);
|
||||
|
||||
final Intent intent = new Intent(this, DesignerActivity.class);
|
||||
intent.putExtra(
|
||||
DesignerActivity.KEY_LAYOUT_PATH,
|
||||
getCurrentEditor().getFile().getAbsolutePath());
|
||||
intent.putStringArrayListExtra(DesignerActivity.KEY_RES_DIRS, getResourceDirectories());
|
||||
LOG.info("Launching UI Designer...");
|
||||
mUIDesignerLauncher.launch(intent);
|
||||
} catch (Throwable th) {
|
||||
LOG.error(getString(R.string.err_cannot_preview_layout), th);
|
||||
getApp().toast(R.string.msg_cannot_preview_layout, Toaster.Type.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
////////////// PRIVATE APIS /////////////////////
|
||||
/////////////////////////////////////////////////
|
||||
@@ -1330,29 +1306,6 @@ public class EditorActivity extends StudioActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void previewLayout() {
|
||||
try {
|
||||
|
||||
if (getCurrentEditor() == null || getCurrentEditor().getFile() == null) {
|
||||
LOG.error("No file is opened. Cannot preview layout.");
|
||||
return;
|
||||
}
|
||||
|
||||
saveAll(false);
|
||||
|
||||
final Intent intent = new Intent(this, DesignerActivity.class);
|
||||
intent.putExtra(
|
||||
DesignerActivity.KEY_LAYOUT_PATH,
|
||||
getCurrentEditor().getFile().getAbsolutePath());
|
||||
intent.putStringArrayListExtra(DesignerActivity.KEY_RES_DIRS, getResourceDirectories());
|
||||
LOG.info("Launching UI Designer...");
|
||||
mUIDesignerLauncher.launch(intent);
|
||||
} catch (Throwable th) {
|
||||
LOG.error(getString(R.string.err_cannot_preview_layout), th);
|
||||
getApp().toast(R.string.msg_cannot_preview_layout, Toaster.Type.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ArrayList<String> getResourceDirectories() {
|
||||
final var dirs = new ArrayList<String>();
|
||||
@@ -1504,7 +1457,7 @@ public class EditorActivity extends StudioActivity
|
||||
}
|
||||
|
||||
private void onSoftInputChanged() {
|
||||
invalidateOptionsMenu();
|
||||
ensureToolbarMenu();
|
||||
if (KeyboardUtils.isSoftInputVisible(this)) {
|
||||
TransitionManager.beginDelayedTransition(mBinding.getRoot(), new Slide(Gravity.TOP));
|
||||
symbolInput.setVisibility(View.VISIBLE);
|
||||
@@ -1563,7 +1516,7 @@ public class EditorActivity extends StudioActivity
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private AlertDialog getFindInProjectDialog() {
|
||||
public AlertDialog getFindInProjectDialog() {
|
||||
return mFindInProjectDialog == null ? createFindInProjectDialog() : mFindInProjectDialog;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
import com.itsaky.androidide.EditorActivity
|
||||
|
||||
/**
|
||||
* Marker class for actions that execute build related tasks.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
abstract class BaseBuildAction : EditorActivityAction() {
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
val context = getActivity(data)
|
||||
if (context == null) {
|
||||
visible = false
|
||||
return
|
||||
} else {
|
||||
visible = true
|
||||
}
|
||||
|
||||
if (isBuildInProgress(context)) {
|
||||
enabled = false
|
||||
return
|
||||
} else {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun postExec(data: ActionData, execResult: Boolean) {
|
||||
val context = getActivity(data) ?: return
|
||||
context.ensureToolbarMenu()
|
||||
}
|
||||
|
||||
fun shouldPrepare() = visible && enabled
|
||||
|
||||
private fun isBuildInProgress(activity: EditorActivity): Boolean =
|
||||
activity.buildServiceHandler.isBuilding
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.views.editor.IDEEditor
|
||||
|
||||
/** @author Akash Yadav */
|
||||
abstract class BaseEditorAction : ActionItem {
|
||||
|
||||
override var label: String = ""
|
||||
override var visible: Boolean = true
|
||||
override var enabled: Boolean = true
|
||||
override var icon: Drawable? = null
|
||||
override var requiresUIThread: Boolean =
|
||||
true // all editor actions must be executed on UI thread
|
||||
override var location: ActionItem.Location = ActionItem.Location.EDITOR_TEXT_ACTIONS
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
getEditor(data)
|
||||
?: kotlin.run {
|
||||
visible = false
|
||||
enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
visible = true
|
||||
enabled = true
|
||||
}
|
||||
|
||||
fun getEditor(data: ActionData): IDEEditor? {
|
||||
return data.get(IDEEditor::class.java)
|
||||
}
|
||||
|
||||
fun getContext(data: ActionData): Context? {
|
||||
val editor = getEditor(data) ?: return null
|
||||
return editor.context
|
||||
}
|
||||
|
||||
fun tintDrawable(context: Context, drawable: Drawable): Drawable {
|
||||
drawable.setTint(
|
||||
ContextCompat.getColor(context, com.itsaky.androidide.R.color.primaryIconColor))
|
||||
return drawable
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import com.itsaky.androidide.EditorActivity
|
||||
|
||||
/** @author Akash Yadav */
|
||||
abstract class EditorActivityAction : ActionItem {
|
||||
|
||||
override var enabled: Boolean = true
|
||||
override var visible: Boolean = true
|
||||
override var icon: Drawable? = null
|
||||
override var label: String = ""
|
||||
override var location: ActionItem.Location = ActionItem.Location.EDITOR_TOOLBAR
|
||||
|
||||
override var requiresUIThread: Boolean = false
|
||||
|
||||
fun getActivity(data: ActionData): EditorActivity? {
|
||||
val context = data.get(Context::class.java) ?: return null
|
||||
return context as EditorActivity
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
/** @author Akash Yadav */
|
||||
abstract class EditorActivityActionMenu : EditorActivityAction(), ActionMenu {
|
||||
override val children: MutableSet<ActionItem> = mutableSetOf()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions
|
||||
|
||||
import com.itsaky.androidide.views.editor.CodeEditorView
|
||||
import java.io.File
|
||||
|
||||
/** @author Akash Yadav */
|
||||
abstract class EditorRelatedAction : EditorActivityAction() {
|
||||
override fun prepare(data: ActionData) {
|
||||
val editor = getEditor(data)
|
||||
val file = data.get(File::class.java)
|
||||
|
||||
visible = editor != null && file != null
|
||||
enabled = visible
|
||||
}
|
||||
|
||||
fun getEditor(data: ActionData): CodeEditorView? = data.get(CodeEditorView::class.java)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.editor
|
||||
|
||||
import android.content.Context
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseEditorAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class CopyAction() : BaseEditorAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.copy)
|
||||
|
||||
val arr = context.obtainStyledAttributes(intArrayOf(android.R.attr.actionModeCopyDrawable))
|
||||
icon = arr.getDrawable(0)?.let { tintDrawable(context, it) }
|
||||
arr.recycle()
|
||||
}
|
||||
|
||||
override val id: String = "ideEditor_copy"
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = getEditor(data) ?: return false
|
||||
editor.copyText()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.editor
|
||||
|
||||
import android.content.Context
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseEditorAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class CutAction() : BaseEditorAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.cut)
|
||||
|
||||
val arr = context.obtainStyledAttributes(intArrayOf(android.R.attr.actionModeCutDrawable))
|
||||
icon = arr.getDrawable(0)?.let { tintDrawable(context, it) }
|
||||
arr.recycle()
|
||||
}
|
||||
|
||||
override val id: String = "ideEditor_cut"
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = getEditor(data) ?: return false
|
||||
editor.cutText()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.editor
|
||||
|
||||
import android.content.Context
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseEditorAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class PasteAction() : BaseEditorAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.paste)
|
||||
|
||||
val arr = context.obtainStyledAttributes(intArrayOf(android.R.attr.actionModePasteDrawable))
|
||||
icon = arr.getDrawable(0)?.let { tintDrawable(context, it) }
|
||||
arr.recycle()
|
||||
}
|
||||
|
||||
override val id: String
|
||||
get() = "ideEditor_paste"
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = getEditor(data) ?: return false
|
||||
editor.pasteText()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.editor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseEditorAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class SelectAllAction() : BaseEditorAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.selectAll)
|
||||
|
||||
val arr = context.obtainStyledAttributes(intArrayOf(android.R.attr.actionModeSelectAllDrawable))
|
||||
icon = arr.getDrawable(0)?.let { tintDrawable(context, it) }
|
||||
arr.recycle()
|
||||
}
|
||||
|
||||
override val id: String = "ideEditor_selectAll"
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = getEditor(data) ?: return false
|
||||
editor.selectAll()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class DaemonStatusAction() : EditorActivityAction() {
|
||||
override val id: String = "editor_daemonStatus"
|
||||
override var requiresUIThread: Boolean = true
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.gradle_daemon_status)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_info)
|
||||
}
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
visible = true
|
||||
enabled = true
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
context.showDaemonStatus()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.GravityCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class FileTreeAction() : EditorActivityAction() {
|
||||
|
||||
override val id: String = "editor_fileTree"
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.msg_file_tree)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_folder)
|
||||
}
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
visible = true
|
||||
enabled = true
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
|
||||
if (!context.binding.root.isDrawerOpen(GravityCompat.END)) {
|
||||
context.binding.root.openDrawer(GravityCompat.END)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.ActionItem
|
||||
import com.itsaky.androidide.actions.ActionMenu
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class FindActionMenu() : EditorActivityAction(), ActionMenu {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.menu_find)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_search)
|
||||
|
||||
addAction(FindInFileAction(context))
|
||||
addAction(FindInProjectAction(context))
|
||||
}
|
||||
|
||||
override val children: MutableSet<ActionItem> = mutableSetOf()
|
||||
override val id: String = "editor_findActions"
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
visible = true
|
||||
enabled = children.size > 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class FindInFileAction() : EditorRelatedAction() {
|
||||
|
||||
override val id: String = "editor_findInFile"
|
||||
override var requiresUIThread: Boolean = true
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.menu_find_file)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_search_file)
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = getEditor(data) ?: return false
|
||||
editor.beginSearch()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.etc
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorActivityAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class FindInProjectAction() : EditorActivityAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.menu_find_project)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_search_project)
|
||||
}
|
||||
|
||||
override val id: String = "editor_findInProject"
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
getActivity(data)
|
||||
?: run {
|
||||
visible = false
|
||||
enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
visible = true
|
||||
enabled = true
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
val dialog = context.findInProjectDialog
|
||||
|
||||
return if (dialog != null) {
|
||||
dialog.show()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.file
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.app.StudioApp
|
||||
import com.itsaky.androidide.utils.Logger
|
||||
import com.itsaky.toaster.Toaster
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class SaveFileAction() : EditorRelatedAction() {
|
||||
|
||||
private val log = Logger.newInstance("SaveFileAction")
|
||||
|
||||
override val id: String = "editor_saveFile"
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.save)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_save)
|
||||
}
|
||||
|
||||
override fun prepare(data: ActionData) {
|
||||
|
||||
val context =
|
||||
getActivity(data)
|
||||
?: run {
|
||||
visible = false
|
||||
enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
visible = context.viewModel.openedFiles.isNotEmpty()
|
||||
enabled = context.areFilesModified()
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
|
||||
return try {
|
||||
// Cannot use context.saveAll() because this.execAction is called on non-UI thread
|
||||
// and saveAll call will result in UI actions
|
||||
context.saveAllResult()
|
||||
true
|
||||
} catch (error: Throwable) {
|
||||
log.error("Failed to save file", error)
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override fun postExec(data: ActionData, execResult: Boolean) {
|
||||
if (execResult) {
|
||||
StudioApp.getInstance().toast(R.string.all_saved, Toaster.Type.SUCCESS)
|
||||
} else {
|
||||
log.error("Failed to save file")
|
||||
TODO("Create message in strings.xml")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.lint
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseBuildAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class LintAction() : BaseBuildAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.lint)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_lint)
|
||||
}
|
||||
|
||||
override val id: String = "editor_lint"
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
|
||||
context.buildServiceHandler.service.lint()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.lint
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseBuildAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class LintDebugAction() : BaseBuildAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.lint_debug)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_run_debug)
|
||||
}
|
||||
|
||||
override val id: String = "editor_lintDebug"
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
|
||||
context.buildServiceHandler.service.lintDebug()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.lint
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.BaseBuildAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class LintReleaseAction() : BaseBuildAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.lint_release)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_run_release)
|
||||
}
|
||||
|
||||
override val id: String = "editor_lintRelease"
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val context = getActivity(data) ?: return false
|
||||
|
||||
context.buildServiceHandler.service.lintRelease()
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.lint
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionItem
|
||||
import com.itsaky.androidide.actions.ActionMenu
|
||||
import com.itsaky.androidide.actions.BaseBuildAction
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class LintTaskMenu() : BaseBuildAction(), ActionMenu {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.lint_tasks)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_lint)
|
||||
|
||||
addAction(LintAction(context))
|
||||
addAction(LintDebugAction(context))
|
||||
addAction(LintReleaseAction(context))
|
||||
}
|
||||
|
||||
override val children: MutableSet<ActionItem> = mutableSetOf()
|
||||
override val id: String = "editor_lintTasks"
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.text
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.views.editor.CodeEditorView
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class RedoAction() : EditorRelatedAction() {
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.redo)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_redo)
|
||||
}
|
||||
|
||||
override val id: String = "editor_redo"
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = data.get(CodeEditorView::class.java)
|
||||
|
||||
return if (editor != null) {
|
||||
editor.redo()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.actions.text
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.itsaky.androidide.R
|
||||
import com.itsaky.androidide.actions.ActionData
|
||||
import com.itsaky.androidide.actions.EditorRelatedAction
|
||||
import com.itsaky.androidide.views.editor.CodeEditorView
|
||||
|
||||
/** @author Akash Yadav */
|
||||
class UndoAction() : EditorRelatedAction() {
|
||||
|
||||
override val id: String = "editor_undo"
|
||||
|
||||
constructor(context: Context) : this() {
|
||||
label = context.getString(R.string.undo)
|
||||
icon = ContextCompat.getDrawable(context, R.drawable.ic_undo)
|
||||
}
|
||||
|
||||
override fun execAction(data: ActionData): Boolean {
|
||||
val editor = data.get(CodeEditorView::class.java)
|
||||
return if (editor != null) {
|
||||
editor.undo()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,10 @@ public class BuildServiceHandler extends IDEHandler implements BuildListener {
|
||||
return service;
|
||||
}
|
||||
|
||||
public boolean isBuilding() {
|
||||
return getService().isBuilding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Objects.requireNonNull(this.activity());
|
||||
@@ -150,7 +154,7 @@ public class BuildServiceHandler extends IDEHandler implements BuildListener {
|
||||
.getApp()
|
||||
.getPrefManager()
|
||||
.putBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false);
|
||||
activity().invalidateOptionsMenu();
|
||||
activity().ensureToolbarMenu();
|
||||
activity().getBinding().buildProgressIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -169,7 +173,7 @@ public class BuildServiceHandler extends IDEHandler implements BuildListener {
|
||||
.getApp()
|
||||
.getPrefManager()
|
||||
.putBoolean(PreferenceManager.KEY_IS_FIRST_PROJECT_BUILD, false);
|
||||
activity().invalidateOptionsMenu();
|
||||
activity().ensureToolbarMenu();
|
||||
activity().getBinding().buildProgressIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.handlers
|
||||
|
||||
import android.content.Context
|
||||
import com.itsaky.androidide.actions.ActionItem
|
||||
import com.itsaky.androidide.actions.ActionsRegistry
|
||||
import com.itsaky.androidide.actions.build.QuickRunAction
|
||||
import com.itsaky.androidide.actions.build.RunActionMenu
|
||||
import com.itsaky.androidide.actions.build.StopDaemonsAction
|
||||
import com.itsaky.androidide.actions.editor.CopyAction
|
||||
import com.itsaky.androidide.actions.editor.CutAction
|
||||
import com.itsaky.androidide.actions.editor.PasteAction
|
||||
import com.itsaky.androidide.actions.editor.SelectAllAction
|
||||
import com.itsaky.androidide.actions.etc.DaemonStatusAction
|
||||
import com.itsaky.androidide.actions.etc.FileTreeAction
|
||||
import com.itsaky.androidide.actions.etc.FindActionMenu
|
||||
import com.itsaky.androidide.actions.file.SaveFileAction
|
||||
import com.itsaky.androidide.actions.text.RedoAction
|
||||
import com.itsaky.androidide.actions.text.UndoAction
|
||||
|
||||
/**
|
||||
* Takes care of registering actions to the actions registry for the editor activity.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
class EditorActivityActions {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun register(context: Context) {
|
||||
val registry = ActionsRegistry.getInstance()
|
||||
|
||||
// Toolbar actions
|
||||
registry.registerAction(UndoAction(context))
|
||||
registry.registerAction(RedoAction(context))
|
||||
registry.registerAction(QuickRunAction(context))
|
||||
registry.registerAction(RunActionMenu(context))
|
||||
registry.registerAction(SaveFileAction(context))
|
||||
registry.registerAction(FindActionMenu(context))
|
||||
registry.registerAction(FileTreeAction(context))
|
||||
registry.registerAction(DaemonStatusAction(context))
|
||||
registry.registerAction(StopDaemonsAction(context))
|
||||
|
||||
// editor text actions
|
||||
registry.registerAction(SelectAllAction(context))
|
||||
registry.registerAction(CutAction(context))
|
||||
registry.registerAction(CopyAction(context))
|
||||
registry.registerAction(PasteAction(context))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun clear() = ActionsRegistry.getInstance().clearActions(ActionItem.Location.EDITOR_TOOLBAR)
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -9,6 +9,7 @@ import java.util.stream.Collectors
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.6.10'
|
||||
|
||||
project.ext {
|
||||
compileSdk = 31
|
||||
buildTools = "31.0.0"
|
||||
@@ -37,10 +38,6 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
//dependencies {
|
||||
// implementation 'com.google.googlejavaformat:google-java-format:1.15.0'
|
||||
//}
|
||||
|
||||
subprojects {
|
||||
apply from: "${rootDir}/gradle/dependencies.gradle"
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@ include ':lsp:api'
|
||||
include ':lsp:java'
|
||||
include ':lsp:xml'
|
||||
include ':lsp:testing'
|
||||
include ':actions'
|
||||
|
||||
Reference in New Issue
Block a user