diff --git a/app/build.gradle b/app/build.gradle index ef708aff1..717dcf6cb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -115,6 +115,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.0' implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0' implementation 'androidx.drawerlayout:drawerlayout:1.1.1' + implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.recyclerview:recyclerview:1.2.1' diff --git a/app/src/main/java/com/itsaky/androidide/EditorActivity.java b/app/src/main/java/com/itsaky/androidide/EditorActivity.java index 37bfcbfa8..1fceb528c 100644 --- a/app/src/main/java/com/itsaky/androidide/EditorActivity.java +++ b/app/src/main/java/com/itsaky/androidide/EditorActivity.java @@ -173,10 +173,6 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F private static final int ACTIONID_OTHERS = 101; private static final int ACTIONID_ALL = 102; - private static final int STD_TYPE_NORMAL = 0; - private static final int STD_TYPE_ERROR = 1; - private static final int STD_TYPE_SUCCESS = 2; - public static final String EXTRA_PROJECT = "project"; private LogReceiver mLogReceiver = new LogReceiver().setLogListener(line -> appendApkLog(line)); diff --git a/app/src/main/java/com/itsaky/androidide/TerminalActivity.java b/app/src/main/java/com/itsaky/androidide/TerminalActivity.java index 24a787426..22e80811a 100644 --- a/app/src/main/java/com/itsaky/androidide/TerminalActivity.java +++ b/app/src/main/java/com/itsaky/androidide/TerminalActivity.java @@ -3,17 +3,23 @@ package com.itsaky.androidide; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; import com.blankj.utilcode.util.ClipboardUtils; import com.blankj.utilcode.util.KeyboardUtils; import com.blankj.utilcode.util.SizeUtils; import com.blankj.utilcode.util.ThrowableUtils; import com.itsaky.androidide.app.StudioActivity; import com.itsaky.androidide.databinding.ActivityTerminalBinding; -import com.itsaky.androidide.managers.ToolsManager; +import com.itsaky.androidide.models.ConstantsBridge; import com.itsaky.androidide.utils.Environment; import com.itsaky.androidide.utils.Logger; import com.itsaky.androidide.utils.TypefaceUtils; +import com.itsaky.androidide.views.virtualkeys.SpecialButton; +import com.itsaky.androidide.views.virtualkeys.VirtualKeyButton; +import com.itsaky.androidide.views.virtualkeys.VirtualKeysConstants; +import com.itsaky.androidide.views.virtualkeys.VirtualKeysInfo; +import com.itsaky.androidide.views.virtualkeys.VirtualKeysView; import com.itsaky.terminal.TerminalEmulator; import com.itsaky.terminal.TerminalSession; import com.itsaky.terminal.TerminalSessionClient; @@ -21,6 +27,7 @@ import com.itsaky.terminal.TextStyle; import com.itsaky.terminal.view.TerminalView; import com.itsaky.terminal.view.TerminalViewClient; import java.util.Map; +import org.json.JSONException; public class TerminalActivity extends StudioActivity { @@ -28,8 +35,10 @@ public class TerminalActivity extends StudioActivity { private TerminalView terminal; private TerminalSession session; + private boolean isVisible = false; private int currentTextSize = 0; + private KeyListener listener; private final Client client = new Client(); private static final Logger LOG = Logger.instance("TerminalActivity"); @@ -38,28 +47,52 @@ public class TerminalActivity extends StudioActivity { binding = ActivityTerminalBinding.inflate(getLayoutInflater()); terminal = new TerminalView(this, null); terminal.setTerminalViewClient(client); - terminal.setTextSize(currentTextSize = SizeUtils.dp2px(10)); - terminal.setTypeface(TypefaceUtils.jetbrainsMono()); terminal.attachSession(createSession()); terminal.setKeepScreenOn(true); + terminal.setTextSize(currentTextSize = SizeUtils.dp2px(10)); + terminal.setTypeface(TypefaceUtils.jetbrainsMono()); - binding.getRoot().addView(terminal, new ViewGroup.LayoutParams(-1, -1)); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, 0); + params.weight = 1f; + binding.getRoot().addView(terminal, 0, params); + try { + binding.virtualKeyTable.setVirtualKeysViewClient(getKeyListener()); + binding.virtualKeyTable.reload(new VirtualKeysInfo(ConstantsBridge.VIRTUAL_KEYS, "", VirtualKeysConstants.CONTROL_CHARS_ALIASES)); + } catch (JSONException e) { + // Won't happen + } + return binding.getRoot(); } + private KeyListener getKeyListener() { + return listener == null ? listener = new KeyListener(terminal) : listener; + } + @Override protected void onResume() { super.onResume(); setTerminalCursorBlinkingState(true); } + @Override + protected void onStart() { + super.onStart(); + isVisible = true; + } + @Override protected void onStop() { super.onStop(); + isVisible = false; setTerminalCursorBlinkingState(false); } + public boolean isVisible() { + return isVisible; + } + private void setTerminalCursorBlinkingState(boolean start ) { if(terminal != null && terminal.mEmulator != null) { terminal.setTerminalCursorBlinkerState(start, true); @@ -76,7 +109,7 @@ public class TerminalActivity extends StudioActivity { } session = new TerminalSession( - Environment.BASH.getAbsolutePath(), // Shell command + Environment.SHELL.getAbsolutePath(), // Shell command Environment.HOME.getAbsolutePath(), // Working directory new String[]{}, // Arguments env, // Environment variables @@ -93,6 +126,70 @@ public class TerminalActivity extends StudioActivity { + private final class KeyListener implements VirtualKeysView.IVirtualKeysView { + + private final TerminalView terminal; + + public KeyListener(TerminalView terminal) { + this.terminal = terminal; + } + + @Override + public void onVirtualKeyButtonClick(View view, VirtualKeyButton buttonInfo, Button button) { + if(terminal == null) return; + if (buttonInfo.isMacro()) { + String[] keys = buttonInfo.getKey().split(" "); + boolean ctrlDown = false; + boolean altDown = false; + boolean shiftDown = false; + boolean fnDown = false; + for (String key : keys) { + if (SpecialButton.CTRL.getKey().equals(key)) { + ctrlDown = true; + } else if (SpecialButton.ALT.getKey().equals(key)) { + altDown = true; + } else if (SpecialButton.SHIFT.getKey().equals(key)) { + shiftDown = true; + } else if (SpecialButton.FN.getKey().equals(key)) { + fnDown = true; + } else { + onTerminalExtraKeyButtonClick(view, key, ctrlDown, altDown, shiftDown, fnDown); + ctrlDown = false; altDown = false; shiftDown = false; fnDown = false; + } + } + } else { + onTerminalExtraKeyButtonClick(view, buttonInfo.getKey(), false, false, false, false); + } + } + + protected void onTerminalExtraKeyButtonClick(View view, String key, boolean ctrlDown, boolean altDown, boolean shiftDown, boolean fnDown) { + if (VirtualKeysConstants.PRIMARY_KEY_CODES_FOR_STRINGS.containsKey(key)) { + Integer keyCode = VirtualKeysConstants.PRIMARY_KEY_CODES_FOR_STRINGS.get(key); + if (keyCode == null) return; + int metaState = 0; + if (ctrlDown) metaState |= KeyEvent.META_CTRL_ON | KeyEvent.META_CTRL_LEFT_ON; + if (altDown) metaState |= KeyEvent.META_ALT_ON | KeyEvent.META_ALT_LEFT_ON; + if (shiftDown) metaState |= KeyEvent.META_SHIFT_ON | KeyEvent.META_SHIFT_LEFT_ON; + if (fnDown) metaState |= KeyEvent.META_FUNCTION_ON; + + KeyEvent keyEvent = new KeyEvent(0, 0, KeyEvent.ACTION_UP, keyCode, 0, metaState); + terminal.onKeyDown(keyCode, keyEvent); + } else { + // not a control char + key.codePoints().forEach(codePoint -> { + terminal.inputCodePoint(codePoint, ctrlDown, altDown); + }); + } + } + + @Override + public boolean performVirtualKeyButtonHapticFeedback(View view, VirtualKeyButton buttonInfo, Button button) { + // No need to handle this + // VirtualKeysView will take care of performing haptic feedback + return false; + } + } + private final class Client implements TerminalViewClient, TerminalSessionClient { @Override diff --git a/app/src/main/java/com/itsaky/androidide/adapters/SymbolInputAdapter.java b/app/src/main/java/com/itsaky/androidide/adapters/SymbolInputAdapter.java index 123626120..91fe6c635 100644 --- a/app/src/main/java/com/itsaky/androidide/adapters/SymbolInputAdapter.java +++ b/app/src/main/java/com/itsaky/androidide/adapters/SymbolInputAdapter.java @@ -1,15 +1,13 @@ package com.itsaky.androidide.adapters; -import android.graphics.Typeface; import android.view.LayoutInflater; import android.view.ViewGroup; -import androidx.core.widget.TextViewCompat; import androidx.recyclerview.widget.RecyclerView; import com.itsaky.androidide.databinding.LayoutSymbolItemBinding; +import com.itsaky.androidide.utils.Symbols; import com.itsaky.androidide.views.SymbolInputView.Symbol; import io.github.rosemoe.editor.widget.CodeEditor; import io.github.rosemoe.editor.widget.SymbolChannel; -import android.util.TypedValue; public class SymbolInputAdapter extends RecyclerView.Adapter { @@ -47,8 +45,7 @@ public class SymbolInputAdapter extends RecyclerView.Adapter channel.insertSymbol(symbol.commit, symbol.offset)); + holder.binding.symbol.setOnClickListener(__ -> channel.insertSymbol(symbol.commit, symbol.offset)); } @Override diff --git a/app/src/main/java/com/itsaky/androidide/fragments/EditorFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/EditorFragment.java index fe264ee2d..7cac089be 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/EditorFragment.java +++ b/app/src/main/java/com/itsaky/androidide/fragments/EditorFragment.java @@ -7,6 +7,7 @@ import android.view.ViewGroup; import com.blankj.utilcode.util.FileIOUtils; import com.blankj.utilcode.util.SizeUtils; import com.itsaky.androidide.adapters.CompletionListAdapter; +import com.itsaky.androidide.app.StudioApp; import com.itsaky.androidide.databinding.FragmentEditorBinding; import com.itsaky.androidide.fragments.preferences.EditorPreferences; import com.itsaky.androidide.interfaces.JLSRequestor; @@ -18,6 +19,7 @@ import com.itsaky.androidide.language.xml.lexer.XMLLexer; import com.itsaky.androidide.managers.PreferenceManager; import com.itsaky.androidide.models.AndroidProject; import com.itsaky.androidide.models.ConstantsBridge; +import com.itsaky.androidide.services.IDEService; import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE; import com.itsaky.androidide.tasks.TaskExecutor; import com.itsaky.androidide.tasks.callables.ReadFileTask; diff --git a/app/src/main/java/com/itsaky/androidide/managers/ToolsManager.java b/app/src/main/java/com/itsaky/androidide/managers/ToolsManager.java index 4ffa75cfc..30a866e0a 100644 --- a/app/src/main/java/com/itsaky/androidide/managers/ToolsManager.java +++ b/app/src/main/java/com/itsaky/androidide/managers/ToolsManager.java @@ -35,7 +35,6 @@ public class ToolsManager { extractLogsenderIfNeeded(); writeInitScript(); - writeBashrc(); rewriteProjectData(); @@ -57,13 +56,6 @@ public class ToolsManager { } } - private static void writeBashrc() { - File rc = Environment.BASHRC; - if(!rc.exists()) { - FileIOUtils.writeFileFromString(rc, BASHRC); - } - } - private static void writeInitScript() { FileIOUtils.writeFileFromString(Environment.INIT_SCRIPT, INIT_SCRIPT); } @@ -80,7 +72,7 @@ public class ToolsManager { final boolean exists = gson && jls && proto; final boolean isOld = JLS_VERSION > prefs.getInt(KEY_JLS_VERSION, 0); - if(true/*!exists || isOld*/) { + if(!exists || isOld) { try { extractJls(); } catch (Throwable e) {} @@ -112,10 +104,6 @@ public class ToolsManager { } catch (IOException e) {} } - private static final String BASHRC = - "PROMPT_DIRTRIM=2" + - "\nPS1=\'\\[\\e[0;34m\\]\\w\\[\\e[0m\\] \\[\\e[0;97m\\]$\\[\\e[0m\\] \'"; - private static final String INIT_SCRIPT = ( "import org.gradle.api.Plugin" + "\nimport org.gradle.api.Project" @@ -183,6 +171,7 @@ public class ToolsManager { + "\n ideProject.displayName = root.getDisplayName()" + "\n ideProject.description = root.getDescription()" + "\n ideProject.path = root.getPath()" + + "\n ideProject.projectDir = root.getProjectDir().getAbsolutePath()" + "\n " + "\n def tasks = root.tasks" + "\n if(tasks != null && tasks.size() > 0) {" @@ -194,6 +183,9 @@ public class ToolsManager { + "\n }" + "\n " + "\n File out = new File(\"@@PROJECT_DATA_FILE@@\")" + + "\n if(out.exists()) {" + + "\n out.delete()" + + "\n }" + "\n out << new JsonBuilder( ideProject ).toPrettyString()" + "\n " + "\n println \">>> PROJECT INITIALIZED <<<\"" @@ -236,6 +228,7 @@ public class ToolsManager { + "\n module.targetSdk = config.targetSdkVersion" + "\n module.versionCode = config.versionCode" + "\n module.versionName = config.versionName" + + "\n module.projectDir = sub.getProjectDir().getAbsolutePath()" + "\n " + "\n if(isApp) {" + "\n module.applicationId = config.applicationId" @@ -301,6 +294,7 @@ public class ToolsManager { + "\n def displayName = \"Not defined\"" + "\n def description = \"Not defined\"" + "\n def path = \"Not defined\"" + + "\n def projectDir = \"Not defined\"" + "\n List modules = new ArrayList()" + "\n List tasks = new ArrayList()" + "\n List dependencies = new ArrayList()" diff --git a/app/src/main/java/com/itsaky/androidide/models/ConstantsBridge.java b/app/src/main/java/com/itsaky/androidide/models/ConstantsBridge.java index db8eea947..2445181a1 100644 --- a/app/src/main/java/com/itsaky/androidide/models/ConstantsBridge.java +++ b/app/src/main/java/com/itsaky/androidide/models/ConstantsBridge.java @@ -21,4 +21,33 @@ public class ConstantsBridge { // Password for GradleApi zip // Real password is gradle-api@admin@androidide public static final String GRADLE_API_ZIP_PASSWORD_HASH = "b50b462f8e8c5789f32428d7e1967da2"; + + + public static final String VIRTUAL_KEYS = + "[" + + "\n [" + + "\n \"ESC\"," + + "\n {" + + "\n \"key\": \"/\"," + + "\n \"popup\": \"\\\\\"" + + "\n }," + + "\n {" + + "\n \"key\": \"-\"," + + "\n \"popup\": \"|\"" + + "\n }," + + "\n \"HOME\"," + + "\n \"UP\"," + + "\n \"END\"," + + "\n \"PGUP\"" + + "\n ]," + + "\n [" + + "\n \"TAB\"," + + "\n \"CTRL\"," + + "\n \"ALT\"," + + "\n \"LEFT\"," + + "\n \"DOWN\"," + + "\n \"RIGHT\"," + + "\n \"PGDN\"" + + "\n ]" + + "\n]"; } diff --git a/app/src/main/java/com/itsaky/androidide/models/project/IDEProject.java b/app/src/main/java/com/itsaky/androidide/models/project/IDEProject.java index 028cbad65..2d3cfc628 100644 --- a/app/src/main/java/com/itsaky/androidide/models/project/IDEProject.java +++ b/app/src/main/java/com/itsaky/androidide/models/project/IDEProject.java @@ -35,6 +35,12 @@ public class IDEProject { @SerializedName("path") public String path = ""; + /** + * Path of the directory containing this project + */ + @SerializedName("projectDir") + public String projectDir; + /** * File path of the application's icon * We get this manually by parsing AndroidManifest.xml diff --git a/app/src/main/java/com/itsaky/androidide/services/IDEService.java b/app/src/main/java/com/itsaky/androidide/services/IDEService.java index 71cdf07fa..a9dcd8032 100644 --- a/app/src/main/java/com/itsaky/androidide/services/IDEService.java +++ b/app/src/main/java/com/itsaky/androidide/services/IDEService.java @@ -25,6 +25,7 @@ import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; +import com.itsaky.androidide.tasks.gradle.resources.ProcessDebugResources; public class IDEService implements ShellServer.Callback { @@ -105,6 +106,13 @@ public class IDEService implements ShellServer.Callback { if(currentTask != null && currentTask.getTaskID() != TASK_SHOW_DEPENDENCIES) listener.onBuildSuccessful(currentTask, charSequence.toString().trim()); appendOutputSeparator(); + + if(currentTask != null && currentTask instanceof ProcessDebugResources) { + /** + * An XML file was changed and saved + * Generaring R.jar + */ + } } else if(charSequence.toString().contains(BUILD_FAILED)) { isBuilding = false; @@ -201,7 +209,11 @@ public class IDEService implements ShellServer.Callback { return TextUtils.join(" ", args); } - + + public IDEProject getIDEProject () { + return mIDEProject; + } + public void execTask(GradleTask task) { execTask(task, false); } @@ -244,19 +256,7 @@ public class IDEService implements ShellServer.Callback { public void bundle() { execTask(BaseGradleTasks.BUNDLE); } - - public void mergeLibAndProjectDex() { - execTask(BaseGradleTasks.MERGE_LIB_AND_PROJECT_DEX); - } - - public void mergeExtDex() { - execTask(BaseGradleTasks.MERGE_EXT_DEX); - } - - public void mergeDex() { - execTask(BaseGradleTasks.MERGE_DEX); - } - + public void clean() { execTask(BaseGradleTasks.CLEAN); } @@ -267,6 +267,11 @@ public class IDEService implements ShellServer.Callback { public void stopAllDaemons() { app.newShell(null).bgAppend("gradle --stop"); + if(isBuilding()) { + if(listener != null) + listener.onBuildFailed(currentTask, getString(R.string.msg_daemons_stopped)); + isBuilding = false; + } } public void lint() { @@ -281,6 +286,10 @@ public class IDEService implements ShellServer.Callback { execTask(BaseGradleTasks.LINT_RELEASE); } + public void processDebugResources() { + execTask(BaseGradleTasks.PROCESS_DEBUG_RESOURCES); + } + public String typeString(int type) { switch (type) { case TASK_SHOW_DEPENDENCIES: diff --git a/app/src/main/java/com/itsaky/androidide/tasks/GradleTask.java b/app/src/main/java/com/itsaky/androidide/tasks/GradleTask.java index 636a082b0..52922214d 100644 --- a/app/src/main/java/com/itsaky/androidide/tasks/GradleTask.java +++ b/app/src/main/java/com/itsaky/androidide/tasks/GradleTask.java @@ -38,4 +38,5 @@ public interface GradleTask { public static final int TASK_LINT_RELEASE = 11; public static final int TASK_TASKS = 12; public static final int TASK_INIT_PROJECT = 13; + public static final int TASK_PROCESS_DEBUG_RESOURCES = 14; } diff --git a/app/src/main/java/com/itsaky/androidide/tasks/gradle/BaseGradleTasks.java b/app/src/main/java/com/itsaky/androidide/tasks/gradle/BaseGradleTasks.java index 975dd4b94..41c699bf3 100644 --- a/app/src/main/java/com/itsaky/androidide/tasks/gradle/BaseGradleTasks.java +++ b/app/src/main/java/com/itsaky/androidide/tasks/gradle/BaseGradleTasks.java @@ -8,17 +8,15 @@ import com.itsaky.androidide.tasks.gradle.build.Bundle; import com.itsaky.androidide.tasks.gradle.build.Clean; import com.itsaky.androidide.tasks.gradle.build.CleanBuild; import com.itsaky.androidide.tasks.gradle.core.Tasks; -import com.itsaky.androidide.tasks.gradle.dex.MergeDex; -import com.itsaky.androidide.tasks.gradle.dex.MergeExtDex; -import com.itsaky.androidide.tasks.gradle.dex.MergeLibAndProjectDex; import com.itsaky.androidide.tasks.gradle.lint.Lint; import com.itsaky.androidide.tasks.gradle.lint.LintDebug; import com.itsaky.androidide.tasks.gradle.lint.LintRelease; import com.itsaky.androidide.tasks.gradle.plugin.InitializeIDEProject; +import com.itsaky.androidide.tasks.gradle.resources.ProcessDebugResources; public class BaseGradleTasks { - public static BaseGradleTask + public static final BaseGradleTask TASKS = new Tasks(), @@ -28,13 +26,12 @@ public class BaseGradleTasks { BUNDLE = new Bundle(), CLEAN = new Clean(), CLEAN_BUILD = new CleanBuild(), + LINT = new Lint(), LINT_DEBUG = new LintDebug(), LINT_RELEASE = new LintRelease(), - - MERGE_DEX = new MergeDex(), - MERGE_EXT_DEX = new MergeExtDex(), - MERGE_LIB_AND_PROJECT_DEX = new MergeLibAndProjectDex(), + + PROCESS_DEBUG_RESOURCES = new ProcessDebugResources(), INITIALIZE_IDE_PROJECT = new InitializeIDEProject(); } diff --git a/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeDex.java b/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeDex.java deleted file mode 100644 index afcfd9a7d..000000000 --- a/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeDex.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.itsaky.androidide.tasks.gradle.dex; - -import com.itsaky.androidide.R; -import com.itsaky.androidide.app.StudioApp; -import com.itsaky.androidide.services.IDEService; -import com.itsaky.androidide.tasks.BaseGradleTask; -import java.io.File; -import java.util.List; -import java.util.Arrays; - -public class MergeDex extends BaseGradleTask { - - @Override - public String getName() { - return StudioApp.getInstance().getString(R.string.task_merge_dex); - } - - @Override - public String getCommands() { - return "mergeDexDebug"; - } - - @Override - public List getTasks() { - return Arrays.asList("mergeDexDebug"); - } - - @Override - public int getTaskID() { - return IDEService.TASK_DEX; - } - - @Override - public boolean canOutput() { - return true; - } - - @Override - public boolean buildsApk() { - return false; - } - - @Override - public File getApk(String buildFolder, String moduleName) { - return null; - } - - @Override - public Type getType() { - return Type.OTHER; - } -} diff --git a/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeExtDex.java b/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeExtDex.java deleted file mode 100644 index 0ff9660ab..000000000 --- a/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeExtDex.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.itsaky.androidide.tasks.gradle.dex; - -import com.itsaky.androidide.R; -import com.itsaky.androidide.app.StudioApp; -import com.itsaky.androidide.services.IDEService; -import com.itsaky.androidide.tasks.BaseGradleTask; -import java.io.File; -import java.util.Arrays; -import java.util.List; - -public class MergeExtDex extends BaseGradleTask { - - @Override - public String getName() { - return StudioApp.getInstance().getString(R.string.task_merge_dex); - } - - @Override - public String getCommands() { - return "mergeExtDexDebug"; - } - - @Override - public List getTasks() { - return Arrays.asList("mergeExtDexDebug"); - } - - @Override - public int getTaskID() { - return IDEService.TASK_DEX; - } - - @Override - public boolean canOutput() { - return true; - } - - @Override - public boolean buildsApk() { - return false; - } - - @Override - public File getApk(String buildFolder, String moduleName) { - return null; - } - - @Override - public Type getType() { - return Type.OTHER; - } -} diff --git a/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeLibAndProjectDex.java b/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeLibAndProjectDex.java deleted file mode 100644 index dc35b7a9b..000000000 --- a/app/src/main/java/com/itsaky/androidide/tasks/gradle/dex/MergeLibAndProjectDex.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.itsaky.androidide.tasks.gradle.dex; - -import com.itsaky.androidide.R; -import com.itsaky.androidide.app.StudioApp; -import com.itsaky.androidide.services.IDEService; -import com.itsaky.androidide.tasks.BaseGradleTask; -import java.io.File; -import java.util.Arrays; -import java.util.List; - -public class MergeLibAndProjectDex extends BaseGradleTask { - - @Override - public String getName() { - return StudioApp.getInstance().getString(R.string.task_merge_dex); - } - - @Override - public String getCommands() { - return "mergeLibDexDebug mergeProjectDexDebug"; - } - - @Override - public List getTasks() { - return Arrays.asList("mergeLibDexDebug", "mergeProjectDexDebug"); - } - - @Override - public int getTaskID() { - return IDEService.TASK_DEX; - } - - @Override - public boolean canOutput() { - return true; - } - - @Override - public boolean buildsApk() { - return false; - } - - @Override - public File getApk(String buildFolder, String moduleName) { - return null; - } - - @Override - public Type getType() { - return Type.OTHER; - } -} diff --git a/app/src/main/java/com/itsaky/androidide/tasks/gradle/resources/ProcessDebugResources.java b/app/src/main/java/com/itsaky/androidide/tasks/gradle/resources/ProcessDebugResources.java new file mode 100644 index 000000000..bd67e0c35 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/tasks/gradle/resources/ProcessDebugResources.java @@ -0,0 +1,50 @@ +package com.itsaky.androidide.tasks.gradle.resources; + +import com.itsaky.androidide.tasks.BaseGradleTask; +import com.itsaky.androidide.tasks.GradleTask; +import java.io.File; +import java.util.List; +import java.util.Arrays; + +public class ProcessDebugResources extends BaseGradleTask { + + @Override + public String getName() { + return "processDebugResources"; + } + + @Override + public String getCommands() { + return "processDebugResources"; + } + + @Override + public List getTasks() { + return Arrays.asList(getCommands()); + } + + @Override + public int getTaskID() { + return TASK_PROCESS_DEBUG_RESOURCES; + } + + @Override + public boolean canOutput() { + return true; + } + + @Override + public boolean buildsApk() { + return false; + } + + @Override + public File getApk(String buildFolder, String moduleName) { + return null; + } + + @Override + public GradleTask.Type getType() { + return Type.BUILD; + } +} diff --git a/app/src/main/java/com/itsaky/androidide/utils/Environment.java b/app/src/main/java/com/itsaky/androidide/utils/Environment.java index 2707f7d03..54c1f9d6b 100644 --- a/app/src/main/java/com/itsaky/androidide/utils/Environment.java +++ b/app/src/main/java/com/itsaky/androidide/utils/Environment.java @@ -38,8 +38,7 @@ public final class Environment { public static final File GRADLE; public static final File JAVA; public static final File BUSYBOX; - public static final File BASH; - public static final File BASHRC; + public static final File SHELL; public static File BOOTCLASSPATH; @@ -77,12 +76,11 @@ public final class Environment { ANDROID_HOME = new File(props.getOrDefault("ANDROID_HOME", DEFAULT_ANDROID_HOME)); JAVA_HOME = new File(props.getOrDefault("JAVA_HOME", DEFAULT_JAVA_HOME)); GRADLE_HOME = new File(props.getOrDefault("GRADLE_HOME", DEFAULT_GRADLE_HOME)); - - BASH = new File(BINDIR, "bash"); + GRADLE = new File(GRADLE_HOME, "bin/gradle"); JAVA = new File(JAVA_HOME, "bin/java"); BUSYBOX = new File(BINDIR, "busybox"); - BASHRC = new File(HOME, ".bashrc"); + SHELL = new File(BINDIR, "sh.sh"); } private static Map readProperties() { @@ -128,7 +126,7 @@ public final class Environment { map.put("PREFIX", SYSROOT.getAbsolutePath()); map.put("BUSYBOX", BUSYBOX.getAbsolutePath()); - map.put("SHELL", BASH.getAbsolutePath()); + map.put("SHELL", SHELL.getAbsolutePath()); map.put("TERM", "xterm-256color"); map.put("COLORTERM", "truecolor"); diff --git a/app/src/main/java/com/itsaky/androidide/utils/Symbols.java b/app/src/main/java/com/itsaky/androidide/utils/Symbols.java index adb74795d..8104dbe4d 100644 --- a/app/src/main/java/com/itsaky/androidide/utils/Symbols.java +++ b/app/src/main/java/com/itsaky/androidide/utils/Symbols.java @@ -1,41 +1,36 @@ package com.itsaky.androidide.utils; +import com.itsaky.androidide.app.StudioApp; import com.itsaky.androidide.fragments.EditorFragment; import com.itsaky.androidide.views.SymbolInputView.Symbol; import java.io.File; -import com.itsaky.androidide.app.StudioApp; public class Symbols { - + public static Symbol[] forFile(File file) { - if(file.isFile()) { - if(file.getName().endsWith(EditorFragment.EXT_JAVA) - || file.getName().endsWith(EditorFragment.EXT_GRADLE)) + if (file.isFile()) { + if (file.getName().endsWith(EditorFragment.EXT_JAVA) + || file.getName().endsWith(EditorFragment.EXT_GRADLE)) return javaSymbols(); - - if(file.getName().endsWith(EditorFragment.EXT_XML)) + + if (file.getName().endsWith(EditorFragment.EXT_XML)) return xmlSymbols(); } - + return new Symbol[0]; } - - private static Symbol tab() { - String tab = createTabSpaces(); - return new Symbol("↹", tab, tab.length()); - } - + public static String createTabSpaces() { int size = StudioApp.getInstance().getPrefManager().getEditorTabSize(); - String tab = ""; - for(int i=1;i<=size;i++) { - tab += " "; + StringBuilder tab = new StringBuilder(); + for (int i=1;i <= size;i++) { + tab.append(" "); } - return tab; + return tab.toString(); } - + public static Symbol[] javaSymbols() { - return new Symbol[]{tab(), + return new Symbol[]{new Symbol("↹", "\t"), new Symbol("{", "{}"), new Symbol("}"), new Symbol("(", "()"), @@ -58,9 +53,9 @@ public class Symbols { new Symbol(":"), new Symbol("_")}; } - + public static Symbol[] xmlSymbols() { - return new Symbol[]{tab(), + return new Symbol[]{new Symbol("↹", "\t"), new Symbol("<", "<>"), new Symbol(">"), new Symbol("/"), @@ -85,5 +80,5 @@ public class Symbols { new Symbol("_"), new Symbol("-")}; } - + } diff --git a/app/src/main/java/com/itsaky/androidide/views/virtualkeys/SpecialButton.java b/app/src/main/java/com/itsaky/androidide/views/virtualkeys/SpecialButton.java new file mode 100644 index 000000000..c50274867 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/views/virtualkeys/SpecialButton.java @@ -0,0 +1,52 @@ +package com.itsaky.androidide.views.virtualkeys; + +import androidx.annotation.NonNull; + +import java.util.HashMap; + +/** The {@link Class} that implements special buttons for {@link VirtualKeysView}. */ +public class SpecialButton { + + private static final HashMap map = new HashMap<>(); + + public static final SpecialButton CTRL = new SpecialButton("CTRL"); + public static final SpecialButton ALT = new SpecialButton("ALT"); + public static final SpecialButton SHIFT = new SpecialButton("SHIFT"); + public static final SpecialButton FN = new SpecialButton("FN"); + + /** The special button key. */ + private final String key; + + /** + * Initialize a {@link SpecialButton}. + * + * @param key The unique key name for the special button. The key is registered in {@link #map} + * with which the {@link SpecialButton} can be retrieved via a call to + * {@link #valueOf(String)}. + */ + public SpecialButton(@NonNull final String key) { + this.key = key; + map.put(key, this); + } + + /** Get {@link #key} for this {@link SpecialButton}. */ + public String getKey() { + return key; + } + + /** + * Get the {@link SpecialButton} for {@code key}. + * + * @param key The unique key name for the special button. + */ + public static SpecialButton valueOf(String key) { + return map.get(key); + } + + @NonNull + @Override + public String toString() { + return key; + } + +} diff --git a/app/src/main/java/com/itsaky/androidide/views/virtualkeys/SpecialButtonState.java b/app/src/main/java/com/itsaky/androidide/views/virtualkeys/SpecialButtonState.java new file mode 100644 index 000000000..993cc4bf6 --- /dev/null +++ b/app/src/main/java/com/itsaky/androidide/views/virtualkeys/SpecialButtonState.java @@ -0,0 +1,49 @@ +package com.itsaky.androidide.views.virtualkeys; + +import android.widget.Button; + +import java.util.ArrayList; +import java.util.List; + +/** The {@link Class} that maintains a state of a {@link SpecialButton} */ +public class SpecialButtonState { + + /** If special button has been created for the {@link VirtualKeysView}. */ + boolean isCreated = false; + /** If special button is active. */ + boolean isActive = false; + /** If special button is locked due to long hold on it and should not be deactivated if its + * state is read. */ + boolean isLocked = false; + + List