diff --git a/app/src/main/java/com/itsaky/androidide/DesignerActivity.java b/app/src/main/java/com/itsaky/androidide/DesignerActivity.java
index 6e1d50568..4fbf39d27 100644
--- a/app/src/main/java/com/itsaky/androidide/DesignerActivity.java
+++ b/app/src/main/java/com/itsaky/androidide/DesignerActivity.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -17,8 +15,6 @@
* along with AndroidIDE. If not, see .
*
**************************************************************************************/
-
-
package com.itsaky.androidide;
import android.content.Context;
@@ -68,6 +64,8 @@ public class DesignerActivity extends StudioActivity {
} catch (Throwable th) {
mBinding.realContainer.removeAllViews();
mBinding.realContainer.addView(createErrorText(th));
+
+ LOG.error (getString(R.string.err_cannot_inflate_layout));
}
}
@@ -88,92 +86,4 @@ public class DesignerActivity extends StudioActivity {
error.setBackgroundColor(ContextCompat.getColor(this, android.R.color.white));
return error;
}
-
- private String printRClassHierarchy () throws IllegalArgumentException, IllegalAccessException {
- return printClassHierarchy(android.R.class, 0);
- }
-
- private String printClassHierarchy (Class> clazz, int indent) throws IllegalArgumentException, IllegalAccessException {
- final StringBuilder sb = new StringBuilder();
- sb.append("class " + clazz.getName() + " {");
- newLineIndent(sb, ++indent);
-
- sb.append("fields : [");
- newLineIndent(sb, ++indent);
- printFields (sb, clazz, indent);
- newLineIndent(sb, --indent);
- sb.append("]");
-
- newLineIndent(sb, indent);
- sb.append("classes : [");
- newLineIndent(sb, ++indent);
- printClasses (sb, clazz, indent);
- newLineIndent(sb, --indent);
- sb.append("]");
-
- return sb.toString();
- }
-
- private void newLineIndent(StringBuilder sb, int indent) {
- sb.append("\n");
- sb.append(repeat(" ", indent * 4));
- }
-
- private void printFields(StringBuilder sb, Class> clazz, int indent) throws IllegalArgumentException, IllegalAccessException {
- boolean first = true;
- for (Field f : clazz.getDeclaredFields()) {
- if (!first) {
- newLineIndent(sb, indent);
- }
- if(!f.isAccessible()) {
- f.setAccessible(true);
- }
- sb.append(f.getName());
- sb.append(" = ");
- if (f.getType() == int[].class) {
- printIntArr(sb, (int[]) f.get(null));
- } else if (f.getType() == int.class) {
- sb.append(f.get(null));
- }
- first = false;
- }
- }
-
- private void printClasses(StringBuilder sb, Class> clazz, int indent) throws IllegalArgumentException, IllegalAccessException {
- boolean first = true;
- for (Class> c : clazz.getClasses()) {
- if (!first) {
- newLineIndent(sb, indent);
- }
- sb.append("class " + c.getSimpleName() + " [");
- newLineIndent(sb, ++indent);
- printFields(sb, c, indent);
- newLineIndent(sb, --indent);
- sb.append("]");
- first = false;
- }
- }
-
- private String repeat (String to, int till) {
- String result = "";
- for (int i=1;i<=till;i++) {
- result += to;
- }
-
- return result;
- }
-
- private void printIntArr (StringBuilder sb, int[] arr) {
- boolean first = true;
- sb.append("[");
- for (int i : arr) {
- if (!first) {
- sb.append(", ");
- }
- sb.append(i);
- first = false;
- }
- sb.append("]");
-
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/DownloadActivity.java b/app/src/main/java/com/itsaky/androidide/DownloadActivity.java
index baef766dc..5a1a9fcaf 100644
--- a/app/src/main/java/com/itsaky/androidide/DownloadActivity.java
+++ b/app/src/main/java/com/itsaky/androidide/DownloadActivity.java
@@ -95,7 +95,7 @@ public class DownloadActivity extends StudioActivity {
.build()
.forResult(abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE);
} catch (Throwable th){
- LOG.error("Unable to start file picker", th);
+ LOG.error(getString (R.string.err_cannot_start_file_picker), th);
}
} else if(id == binding.install.getId()) {
if(choosenDir == null) {
@@ -134,10 +134,10 @@ public class DownloadActivity extends StudioActivity {
new Thread (reader).start();
} catch (DownloadActivity.InstallationException e) {
- LOG.error("Installation error", e);
+ LOG.error(getString(R.string.err_installation), e);
onInstallationFailed(e.exitCode);
} catch (IOException e) {
- LOG.error("Installation error", e);
+ LOG.error(getString(R.string.err_installation), e);
onInstallationFailed(5); // Exit code 5 : I/O Error
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/EditorActivity.java b/app/src/main/java/com/itsaky/androidide/EditorActivity.java
index ed3214749..896015025 100644
--- a/app/src/main/java/com/itsaky/androidide/EditorActivity.java
+++ b/app/src/main/java/com/itsaky/androidide/EditorActivity.java
@@ -270,7 +270,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
saveAll(false /* No notification */);
saved = true;
} catch (Throwable th) {
- LOG.error(":onPause(): Failed to save files", th);
+ LOG.error(getString(R.string.err_cannot_save_files), th);
saved = false;
}
@@ -1081,7 +1081,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
intent.putExtra(DesignerActivity.KEY_LAYOUT_PATH, mCurrentFile.getAbsolutePath());
startActivity(intent);
} catch (Throwable th) {
- LOG.error("Unable to preview layout", th);
+ LOG.error(getString(R.string.err_cannot_preview_layout), th);
getApp().toast(R.string.msg_cannot_preview_layout, Toaster.Type.ERROR);
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/app/StudioApp.java b/app/src/main/java/com/itsaky/androidide/app/StudioApp.java
index 05c1f4874..53d0219ba 100644
--- a/app/src/main/java/com/itsaky/androidide/app/StudioApp.java
+++ b/app/src/main/java/com/itsaky/androidide/app/StudioApp.java
@@ -92,7 +92,7 @@ public class StudioApp extends BaseApplication {
mXmlCompletionService = new XMLCompletionService (mAttrInfo, mWidgetInfo);
} catch (Throwable th) {
- LOG.error ("Unable to start XML completion service", th);
+ LOG.error (getString (com.itsaky.androidide.R.string.err_init_sdkinfo), th);
}
}, "SDK Information Loader").start();
}
diff --git a/app/src/main/java/com/itsaky/androidide/language/java/JavaAutoComplete.java b/app/src/main/java/com/itsaky/androidide/language/java/JavaAutoComplete.java
index 266d8f15d..a5d18efec 100644
--- a/app/src/main/java/com/itsaky/androidide/language/java/JavaAutoComplete.java
+++ b/app/src/main/java/com/itsaky/androidide/language/java/JavaAutoComplete.java
@@ -33,6 +33,7 @@ import org.eclipse.lsp4j.CompletionParams;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
+import com.itsaky.androidide.app.StudioApp;
public class JavaAutoComplete implements AutoCompleteProvider {
@@ -66,10 +67,10 @@ public class JavaAutoComplete implements AutoCompleteProvider {
}
} catch (Throwable th) {
- LOG.error("CompletionError", th);
+ LOG.error(StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_completion), th);
}
} else {
- LOG.error("Cannot compute completions for Java file. No LanguageServer implementation found.");
+ LOG.error(StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_no_server_implementation));
}
return new ArrayList();
}
diff --git a/app/src/main/java/com/itsaky/androidide/lsp/AsynchronousSocketLauncher.java b/app/src/main/java/com/itsaky/androidide/lsp/AsynchronousSocketLauncher.java
index bf3a94915..c0d84f4dd 100644
--- a/app/src/main/java/com/itsaky/androidide/lsp/AsynchronousSocketLauncher.java
+++ b/app/src/main/java/com/itsaky/androidide/lsp/AsynchronousSocketLauncher.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -17,8 +15,6 @@
* along with AndroidIDE. If not, see .
*
**************************************************************************************/
-
-
package com.itsaky.androidide.lsp;
import androidx.annotation.RequiresApi;
@@ -80,4 +76,9 @@ public class AsynchronousSocketLauncher extends LSPClientLauncher {
CloseUtils.closeIOQuietly(serverSocket);
}
+
+ @Override
+ public String getLanguageCode() {
+ return "";
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/lsp/LSPClientLauncher.java b/app/src/main/java/com/itsaky/androidide/lsp/LSPClientLauncher.java
index c59718173..171d09c80 100644
--- a/app/src/main/java/com/itsaky/androidide/lsp/LSPClientLauncher.java
+++ b/app/src/main/java/com/itsaky/androidide/lsp/LSPClientLauncher.java
@@ -28,6 +28,7 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import java.util.Locale;
+import com.itsaky.androidide.app.StudioApp;
/**
* Launches a client for a Language server and handles connection.
@@ -83,7 +84,7 @@ public abstract class LSPClientLauncher extends Thread {
try {
launch();
} catch (Throwable th) {
- LOG.error("Error starting language server", th);
+ LOG.error(StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_cannot_start_server, getLanguageCode()), th);
}
}
@@ -111,6 +112,11 @@ public abstract class LSPClientLauncher extends Thread {
*/
public abstract void shutdown();
+ /**
+ * Get the language code for the server
+ */
+ public abstract String getLanguageCode();
+
/**
* A listener to listen for language server start event.
*/
@@ -195,7 +201,7 @@ public abstract class LSPClientLauncher extends Thread {
this.out.write(data.data);
this.out.flush();
} catch (Throwable e) {
- LOG.error ("Failed to write to LSP4J socket", e);
+ LOG.error (StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_cannot_write_socket), e);
}
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/lsp/StandardStreamsLauncher.java b/app/src/main/java/com/itsaky/androidide/lsp/StandardStreamsLauncher.java
index 4c27cd2eb..72a889488 100644
--- a/app/src/main/java/com/itsaky/androidide/lsp/StandardStreamsLauncher.java
+++ b/app/src/main/java/com/itsaky/androidide/lsp/StandardStreamsLauncher.java
@@ -25,6 +25,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Future;
import org.eclipse.lsp4j.jsonrpc.Launcher;
+import com.itsaky.androidide.app.StudioApp;
public class StandardStreamsLauncher extends LSPClientLauncher {
@@ -56,8 +57,7 @@ public class StandardStreamsLauncher extends LSPClientLauncher {
listening.get();
} catch (Throwable th) {
LOG.error (
- "---> StandardStreamsLauncher <---",
- "An error occured while waiting for language server process to stop",
+ StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_server_disconnected),
th
);
}
@@ -79,4 +79,9 @@ public class StandardStreamsLauncher extends LSPClientLauncher {
CloseUtils.closeIO(in, out);
}
+
+ @Override
+ public String getLanguageCode() {
+ return this.langCode;
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/lsp/handlers/JLSHandler.java b/app/src/main/java/com/itsaky/androidide/lsp/handlers/JLSHandler.java
index 312975181..c254f0d76 100644
--- a/app/src/main/java/com/itsaky/androidide/lsp/handlers/JLSHandler.java
+++ b/app/src/main/java/com/itsaky/androidide/lsp/handlers/JLSHandler.java
@@ -78,7 +78,7 @@ public class JLSHandler implements LSPHandler {
mLauncher.start();
} catch (Throwable th) {
- LOG.error("Unable to start Java Language server", th);
+ LOG.error(StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_cannot_start_server, LSPProvider.LANGUAGE_JAVA), th);
}
}
@@ -88,7 +88,7 @@ public class JLSHandler implements LSPHandler {
final IDELanguageServer server = LSPProvider.getServerForLanguage(LSPProvider.LANGUAGE_JAVA);
if (server == null) {
- LOG.error ("Cannot initialize Java Language Server. Server instance is null!");
+ LOG.error (StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_no_server_implementation));
return Optional.empty();
}
@@ -119,7 +119,7 @@ public class JLSHandler implements LSPHandler {
}
return Optional.of(result);
} catch (Throwable e) {
- LOG.error ("An error occurred while initializing language server.", e);
+ LOG.error (StudioApp.getInstance().getString(com.itsaky.androidide.R.string.err_init_server), e);
return Optional.empty();
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/services/builder/BuildListener.java b/app/src/main/java/com/itsaky/androidide/services/builder/BuildListener.java
index fcb7a3523..6d6b6f2c5 100644
--- a/app/src/main/java/com/itsaky/androidide/services/builder/BuildListener.java
+++ b/app/src/main/java/com/itsaky/androidide/services/builder/BuildListener.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -17,8 +15,6 @@
* along with AndroidIDE. If not, see .
*
**************************************************************************************/
-
-
package com.itsaky.androidide.services.builder;
import com.itsaky.androidide.project.IDEModule;
diff --git a/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java b/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java
index 9ec512577..bccd41ef1 100644
--- a/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java
+++ b/app/src/main/java/com/itsaky/androidide/services/builder/IDEService.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -17,7 +15,6 @@
* along with AndroidIDE. If not, see .
*
**************************************************************************************/
-
package com.itsaky.androidide.services.builder;
import androidx.annotation.StringRes;
@@ -151,12 +148,12 @@ public class IDEService {
text = line.replace(app.getRootDir().getAbsolutePath(), "HOME");
}
if (line.contains(app.getRootDir().getParentFile().getAbsolutePath())) {
- text = line.replace(app.getRootDir().getParentFile().getAbsolutePath(), "ROOT_DIR");
+ text = line.replace(app.getRootDir().getParentFile().getAbsolutePath(), "ROOT");
}
listener.appendOutput(currentTask, text);
- if(line.contains(RUN_TASK)) {
+ if(line.startsWith(RUN_TASK)) {
listener.onRunTask(currentTask, line.trim());
} else if(line.startsWith(STARTING_DAEMON)) {
listener.onStartingGradleDaemon(currentTask);
diff --git a/app/src/main/java/com/itsaky/androidide/services/builder/MainThreadBuildListener.java b/app/src/main/java/com/itsaky/androidide/services/builder/MainThreadBuildListener.java
index 275820faa..8e73e6249 100644
--- a/app/src/main/java/com/itsaky/androidide/services/builder/MainThreadBuildListener.java
+++ b/app/src/main/java/com/itsaky/androidide/services/builder/MainThreadBuildListener.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -17,8 +15,6 @@
* along with AndroidIDE. If not, see .
*
**************************************************************************************/
-
-
package com.itsaky.androidide.services.builder;
import com.blankj.utilcode.util.ThreadUtils;
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6ca163cfa..ed517a3bf 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -275,4 +275,19 @@
Please choose default font size of editor :
This will delete caches directory created by Gradle. If you delete it, the next build may take a bit longer than normal as Gradle will download required files again.\nIMPORTANT: This will also delete AAPT2. You will need to reinstall it otherwise you\'ll end up with a build failure.\n\nAre you sure you want to delete caches?
+
+
+ Installation error
+ Completion error
+ No LanguageServer implementation found.
+ Error initializing language server
+ Unable to initialize SDK Info
+ Unable to start file picker
+ Failed to parse APK metadata
+ Unable to save files
+ Unable to preview layout
+ Unable to inflate layout
+ Unable to start Language Server for: %s
+ Failed to write to Socket stream
+ Language server process unexpectedly exited.
diff --git a/layout-inflater/build.gradle b/layout-inflater/build.gradle
index e0920273f..1b71ff6fd 100644
--- a/layout-inflater/build.gradle
+++ b/layout-inflater/build.gradle
@@ -32,5 +32,6 @@ dependencies {
implementation 'com.blankj:utilcodex:1.30.6'
implementation 'org.jsoup:jsoup:1.14.2'
+ implementation project (":common")
api project (':sdk-info')
}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/inflater/XMLLayoutInflater.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/inflater/XMLLayoutInflater.java
index d833a402f..dd4acd74e 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/inflater/XMLLayoutInflater.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/inflater/XMLLayoutInflater.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -27,8 +25,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
-import com.itsaky.androidide.ui.resources.ResourceTable;
-import com.itsaky.androidide.ui.resources.ResourceTableFactory;
import com.itsaky.androidide.ui.util.Preconditions;
import com.itsaky.androidide.ui.view.IAttribute;
import com.itsaky.androidide.ui.view.IAttributeAdapter;
@@ -65,7 +61,6 @@ class XMLLayoutInflater extends BaseLayoutInflater {
private final Set resDirs;
private final AttrInfo attrInfo;
private final WidgetInfo widgetInfo;
- private final ResourceTable frameworkResourceTable;
private final IResourceFinder resFinder;
private ContextProvider contextProvider;
@@ -94,9 +89,8 @@ class XMLLayoutInflater extends BaseLayoutInflater {
this.widgetInfo = config.widgetInfo;
this.resFinder = config.resFinder;
this.contextProvider = config.contextProvider;
- this.frameworkResourceTable = ResourceTableFactory.newFrameworkResourceTable();
- Preconditions.assertAllNotNull("LayoutInflater parameters cannot be null", resDirs, attrInfo, widgetInfo, resFinder, frameworkResourceTable);
+ Preconditions.assertAllNotNull("LayoutInflater parameters cannot be null", resDirs, attrInfo, widgetInfo, resFinder);
}
@Override
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/AttributeResource.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/AttributeResource.java
deleted file mode 100644
index 12c1e5536..000000000
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/AttributeResource.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- *
-**************************************************************************************/
-package com.itsaky.androidide.ui.resources;
-
-import androidx.annotation.NonNull;
-import java.util.regex.Pattern;
-
-public class AttributeResource {
- public static final String ANDROID_NS = "http://schemas.android.com/apk/res/android";
- public static final String ANDROID_RES_NS_PREFIX = "http://schemas.android.com/apk/res/";
- public static final String RES_AUTO_NS_URI = "http://schemas.android.com/apk/res-auto";
-
- public static final String NULL_VALUE = "@null";
- public static final String EMPTY_VALUE = "@empty";
- public static final Pattern IS_RESOURCE_REFERENCE = Pattern.compile("^\\s*@");
-
- public final @NonNull ResName resName;
- public final @NonNull String value;
- public final @NonNull String trimmedValue;
- public final @NonNull String contextPackageName;
- private final Integer referenceResId;
-
- public AttributeResource(@NonNull ResName resName, @NonNull String value, @NonNull String contextPackageName) {
- this(resName, value, contextPackageName, null);
- }
-
- public AttributeResource(@NonNull ResName resName, @NonNull String value, @NonNull String contextPackageName, Integer referenceResId) {
- this.referenceResId = referenceResId;
- if (!resName.type.equals("attr")) throw new IllegalStateException("\"" + resName.getFullyQualifiedName() + "\" unexpected");
-
- this.resName = resName;
- this.value = value;
- this.trimmedValue = value.trim();
- this.contextPackageName = contextPackageName;
- }
-
- public boolean isResourceReference() {
- return isResourceReference(trimmedValue);
- }
-
- public @NonNull ResName getResourceReference() {
- if (!isResourceReference()) throw new RuntimeException("not a resource reference: " + this);
- return ResName.qualifyResName(deref(trimmedValue).replace("+", ""), contextPackageName, "style");
- }
-
- public boolean isStyleReference() {
- return isStyleReference(trimmedValue);
- }
-
- public ResName getStyleReference() {
- if (!isStyleReference()) throw new RuntimeException("not a style reference: " + this);
- return ResName.qualifyResName(value.substring(1), contextPackageName, "attr");
- }
-
- public boolean isNull() {
- return NULL_VALUE.equals(trimmedValue);
- }
-
- public boolean isEmpty() {
- return EMPTY_VALUE.equals(trimmedValue);
- }
-
- @Override
- public String toString() {
- return "Attribute{" +
- "name='" + resName + '\'' +
- ", value='" + value + '\'' +
- ", contextPackageName='" + contextPackageName + '\'' +
- '}';
- }
-
- public static boolean isResourceReference(String value) {
- return IS_RESOURCE_REFERENCE.matcher(value).find() && !isNull(value);
- }
-
- public static @NonNull ResName getResourceReference(String value, String defPackage, String defType) {
- if (!isResourceReference(value)) throw new IllegalArgumentException("not a resource reference: " + value);
- return ResName.qualifyResName(deref(value).replace("+", ""), defPackage, defType);
- }
-
- private static @NonNull String deref(@NonNull String value) {
- return value.substring(value.indexOf('@') + 1);
- }
-
- public static boolean isStyleReference(String value) {
- return value.startsWith("?");
- }
-
- public static ResName getStyleReference(String value, String defPackage, String defType) {
- if (!isStyleReference(value)) throw new IllegalArgumentException("not a style reference: " + value);
- return ResName.qualifyResName(value.substring(1), defPackage, defType);
- }
-
- public static boolean isNull(String value) {
- return NULL_VALUE.equals(value);
- }
-
- public static boolean isEmpty(String value) {
- return EMPTY_VALUE.equals(value);
- }
-
- public Integer getReferenceResId() {
- return referenceResId;
- }
-}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResName.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResName.java
deleted file mode 100644
index d349235ac..000000000
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResName.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- *
-**************************************************************************************/
-package com.itsaky.androidide.ui.resources;
-
-import androidx.annotation.NonNull;
-import java.io.File;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class ResName {
- public static final String ID_TYPE = "id";
-
- private static final Pattern FQN_PATTERN = Pattern.compile("^([^:]*):([^/]+)/(.+)$");
- private static final int NAMESPACE = 1;
- private static final int TYPE = 2;
- private static final int NAME = 3;
-
- public final @NonNull String packageName;
- public final @NonNull String type;
- public final @NonNull String name;
-
- public final int hashCode;
-
- public ResName(@NonNull String packageName, @NonNull String type, @NonNull String name) {
- this.packageName = packageName;
- this.type = type.trim();
- this.name = name.trim();
-
- hashCode = computeHashCode();
- }
-
- public ResName(@NonNull String fullyQualifiedName) {
- Matcher matcher = FQN_PATTERN.matcher(fullyQualifiedName.trim());
- if (!matcher.find()) {
- throw new IllegalStateException("\"" + fullyQualifiedName + "\" is not fully qualified");
- }
- packageName = matcher.group(NAMESPACE);
- type = matcher.group(TYPE).trim();
- name = matcher.group(NAME).trim();
-
- hashCode = computeHashCode();
- if (packageName.equals("xmlns")) throw new IllegalStateException("\"" + fullyQualifiedName + "\" unexpected");
- }
-
- /**
- * @return null if the resource could not be qualified.
- */
- public static String qualifyResourceName(@NonNull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
- ResName resName = qualifyResName(possiblyQualifiedResourceName, defaultPackageName, defaultType);
- return resName != null ? resName.getFullyQualifiedName() : null;
- }
-
- public static ResName qualifyResName(@NonNull String possiblyQualifiedResourceName, ResName defaults) {
- return qualifyResName(possiblyQualifiedResourceName, defaults.packageName, defaults.type);
- }
-
- public static ResName qualifyResName(@NonNull String possiblyQualifiedResourceName, String defaultPackageName, String defaultType) {
- int indexOfColon = possiblyQualifiedResourceName.indexOf(':');
- int indexOfSlash = possiblyQualifiedResourceName.indexOf('/');
- String type = null;
- String packageName = null;
- String name = possiblyQualifiedResourceName;
- if (indexOfColon > indexOfSlash) {
- if (indexOfSlash > 0) {
- type = possiblyQualifiedResourceName.substring(0, indexOfSlash);
- }
- packageName = possiblyQualifiedResourceName.substring(indexOfSlash + 1, indexOfColon);
- name = possiblyQualifiedResourceName.substring(indexOfColon + 1);
- } else if (indexOfSlash > indexOfColon) {
- if (indexOfColon > 0) {
- packageName = possiblyQualifiedResourceName.substring(0, indexOfColon);
- }
- type = possiblyQualifiedResourceName.substring(indexOfColon + 1, indexOfSlash);
- name = possiblyQualifiedResourceName.substring(indexOfSlash + 1);
- }
-
- if ((type == null && defaultType == null) || (packageName == null && defaultPackageName == null)) {
- return null;
- }
-
- if (packageName == null) {
- packageName = defaultPackageName;
- } else if ("*android".equals(packageName)) {
- packageName = "android";
- }
-
- return new ResName(packageName, type == null ? defaultType : type, name);
- }
-
- public static String qualifyResName(String possiblyQualifiedResourceName, String contextPackageName) {
- if (possiblyQualifiedResourceName == null) {
- return null;
- }
-
- if (AttributeResource.isNull(possiblyQualifiedResourceName)) {
- return null;
- }
-
- // Was not able to fully qualify the resource name
- String fullyQualifiedResourceName = qualifyResourceName(possiblyQualifiedResourceName, contextPackageName, null);
- if (fullyQualifiedResourceName == null) {
- return null;
- }
-
- return fullyQualifiedResourceName.replaceAll("[@+]", "");
- }
-
- public static ResName qualifyFromFilePath(@NonNull final String packageName, @NonNull final String filePath) {
- final File file = new File(filePath);
- final String type = file.getParentFile().getName().split("-", 0)[0];
- final String name = baseNameFor(file.getName());
-
- return new ResName(packageName, type, name);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- ResName resName = (ResName) o;
-
- if (hashCode() != resName.hashCode()) return false;
-
- if (!packageName.equals(resName.packageName)) return false;
- if (!type.equals(resName.type)) return false;
- if (!name.equals(resName.name)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
-
- @Override
- public String toString() {
- return "ResName{" + getFullyQualifiedName() + "}";
- }
-
- public String getFullyQualifiedName() {
- return packageName + ":" + type + "/" + name;
- }
-
- public String getNamespaceUri() {
- return "http://schemas.android.com/apk/res/" + packageName;
- }
-
- public ResName withPackageName(String packageName) {
- if (packageName.equals(this.packageName)) return this;
- return new ResName(packageName, type, name);
- }
-
- public void mustBe(String expectedType) {
- if (!type.equals(expectedType)) {
- throw new RuntimeException("expected " + getFullyQualifiedName() + " to be a " + expectedType + ", is a " + type);
- }
- }
-
- private int computeHashCode() {
- int result = packageName.hashCode();
- result = 31 * result + type.hashCode();
- result = 31 * result + name.hashCode();
- return result;
- }
-
- static String baseNameFor(String name) {
- int dotIndex = name.indexOf(".");
- return dotIndex >= 0 ? name.substring(0, dotIndex) : name;
- }
-}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceIdGenerator.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceIdGenerator.java
deleted file mode 100644
index 29c4c834f..000000000
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceIdGenerator.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- *
-**************************************************************************************/
-package com.itsaky.androidide.ui.resources;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class ResourceIdGenerator {
-
- private final Map typeInfo = new HashMap<>();
- private int packageIdentifier;
-
- private static class TypeTracker {
- private int typeIdentifier;
- private int currentMaxEntry;
-
- TypeTracker(int typeIdentifier) {
- this.typeIdentifier = typeIdentifier;
- }
-
- void record(int entryIdentifier) {
- currentMaxEntry = Math.max(currentMaxEntry, entryIdentifier);
- }
-
- public int getFreeIdentifier() {
- return ++currentMaxEntry;
- }
-
- public int getTypeIdentifier() {
- return typeIdentifier;
- }
- }
-
- ResourceIdGenerator(int packageIdentifier) {
- this.packageIdentifier = packageIdentifier;
- }
-
- public void record(int resId, String type, String name) {
- TypeTracker typeTracker = typeInfo.get(type);
- if (typeTracker == null) {
- typeTracker = new TypeTracker(ResourceIds.getTypeIdentifier(resId));
- typeInfo.put(type, typeTracker);
- }
- typeTracker.record(ResourceIds.getEntryIdentifier(resId));
- }
-
- public int generate(String type, String name) {
- TypeTracker typeTracker = typeInfo.get(type);
- if (typeTracker == null) {
- typeTracker = new TypeTracker(getNextFreeTypeIdentifier());
- typeInfo.put(type, typeTracker);
- }
- return ResourceIds.makeIdentifer(packageIdentifier, typeTracker.getTypeIdentifier(), typeTracker.getFreeIdentifier());
- }
-
- private int getNextFreeTypeIdentifier() {
- int result = 0;
- for (TypeTracker typeTracker : typeInfo.values()) {
- result = Math.max(result, typeTracker.getTypeIdentifier());
- }
- return ++result;
- }
-}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceIds.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceIds.java
deleted file mode 100644
index 6d72960a7..000000000
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceIds.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- *
-**************************************************************************************/
-package com.itsaky.androidide.ui.resources;
-
-public class ResourceIds {
- public static boolean isFrameworkResource(int resId) {
- return ((resId >>> 24) == 0x1);
- }
-
- public static int getPackageIdentifier(int resId) {
- return (resId >>> 24);
- }
-
- public static int getTypeIdentifier(int resId) {
- return (resId & 0x00FF0000) >>> 16;
- }
-
- public static int getEntryIdentifier(int resId) {
- return resId & 0x0000FFFF;
- }
-
- public static int makeIdentifer(int packageIdentifier, int typeIdentifier, int entryIdenifier) {
- return packageIdentifier << 24 | typeIdentifier << 16 | entryIdenifier;
- }
-}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceTable.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceTable.java
deleted file mode 100644
index eda013f08..000000000
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceTable.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- *
-**************************************************************************************/
-package com.itsaky.androidide.ui.resources;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-
-public class ResourceTable {
-
- private int packageIdentifier = 0;
- private final String packageName;
- private final BiMap resourceTable = HashBiMap.create();
-
- private final ResourceIdGenerator androidResourceIdGenerator = new ResourceIdGenerator(0x01);
-
- public ResourceTable(String packageName) {
- this.packageName = packageName;
- }
-
- public Integer getResourceId(ResName resName) {
- Integer id = resourceTable.inverse().get(resName);
- if (id == null && resName != null && resName.name.contains(".")) {
- id = resourceTable.inverse().get(new ResName(resName.packageName, resName.type, underscorize(resName.name)));
- }
- return id != null ? id : 0;
- }
-
- public int getPackageIdentifier() {
- return packageIdentifier;
- }
-
- void addResource(int resId, String type, String name) {
- if (ResourceIds.isFrameworkResource(resId)) {
- androidResourceIdGenerator.record(resId, type, name);
- }
- ResName resName = new ResName(packageName, type, name);
- int resIdPackageIdentifier = ResourceIds.getPackageIdentifier(resId);
- if (getPackageIdentifier() == 0) {
- this.packageIdentifier = resIdPackageIdentifier;
- } else if (getPackageIdentifier() != resIdPackageIdentifier) {
- throw new IllegalArgumentException("Incompatible package for " + packageName + ":" + type + "/" + name + " with resId " + resIdPackageIdentifier + " to ResourceIndex with packageIdentifier " + getPackageIdentifier());
- }
-
- ResName existingEntry = resourceTable.put(resId, resName);
- if (existingEntry != null && !existingEntry.equals(resName)) {
- throw new IllegalArgumentException("ResId " + Integer.toHexString(resId) + " mapped to both " + resName + " and " + existingEntry);
- }
- }
-
- private static String underscorize(String s) {
- return s == null ? null : s.replace('.', '_');
- }
-}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceTableFactory.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceTableFactory.java
deleted file mode 100644
index 6a58413c1..000000000
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/resources/ResourceTableFactory.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
- *
- * AndroidIDE is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * AndroidIDE is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with AndroidIDE. If not, see .
- *
-**************************************************************************************/
-package com.itsaky.androidide.ui.resources;
-
-import androidx.annotation.Nullable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ResourceTableFactory {
-
- @Nullable
- public static ResourceTable newFrameworkResourceTable () {
- final ResourceTable table = new ResourceTable ("android");
- final Class> androidR = android.R.class;
- try {
- processResources(table, androidR);
- } catch (IllegalArgumentException|IllegalAccessException e) {
- return null;
- }
- return table;
- }
-
- private static void processResources(ResourceTable table, Class> rClass) throws IllegalArgumentException, IllegalAccessException {
- final Map> styleableMap = new HashMap<>();
- for (Class> innerClass : rClass.getClasses()) {
- if ("styleable".equals(innerClass.getSimpleName())) {
- for (final Field attr : innerClass.getDeclaredFields()) {
- final Class> attrClassType = attr.getType();
- if (attrClassType == int[].class) { // declaration
- addStyleableGroup (styleableMap, attr);
- } else if (attrClassType == int.class) { // Member of
- addStyleableMember (table, styleableMap, attr);
- }
- }
- } else {
- for (Field field : innerClass.getDeclaredFields()) {
- if (field.getType().equals(Integer.TYPE) && Modifier.isStatic(field.getModifiers())) {
- int id = field.getInt(null);
- String resourceName = field.getName();
- if (id != 0) {
- table.addResource(id, innerClass.getSimpleName(), resourceName);
- }
- }
- }
- }
- }
- }
-
- private static void addStyleableGroup(final Map> styleableMap, final Field attr) throws IllegalArgumentException, IllegalAccessException {
- final String name = attr.getName();
- List members = styleableMap.get(name);
- if (members == null) {
- members = new ArrayList<>();
- }
- final int[] mm = (int[]) attr.get(null);
- if (mm == null || mm.length <= 0) {
- return;
- }
-
- for (int i=0;i> styleableMap, final Field attr) throws IllegalArgumentException, IllegalAccessException {
- final String name = attr.getName();
- final int separator = findGroupAndAttrNameSeparator (styleableMap, name); // If this is a member, then the name will definitely contain am underscore
- final String groupName = name.substring(0, separator);
- final String attrName = name.substring(separator + 1);
-
- final List members = styleableMap.get(groupName);
- if (members == null) {
- throw new IllegalStateException ("No styleable declared for " + groupName + "\nstyleableMap = " + styleableMap); // No entry for this name
- }
-
- final int index = (int) attr.get(null);
- if (index < 0 || index >= members.size()) {
- throw new IndexOutOfBoundsException ("Index " + index + " is out of bounds (size=" + members.size() + "). name=" + name + ", grpName=" + groupName + ", attrName=" + attrName);
- }
-
- table.addResource(members.get(index), "attr", attrName);
- }
-
- private static int findGroupAndAttrNameSeparator(Map> styleableMap, String name) {
- int index = name.length() - 1;
-
- while (index > 0) {
- int i = name.lastIndexOf("_", index);
- String group = name.substring(0, i);
- List mm = styleableMap.get(group);
- if (mm != null) {
- return i;
- } else {
- index = i - 1;
- }
- }
-
- return -1;
- }
-}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IView.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IView.java
index cc8c61f59..694b5f577 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IView.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IView.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IViewGroup.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IViewGroup.java
index 50164ece4..3eec14c28 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IViewGroup.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/IViewGroup.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewAttrAdapter.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewAttrAdapter.java
index dfd5131be..50554721d 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewAttrAdapter.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewAttrAdapter.java
@@ -1,7 +1,5 @@
/************************************************************************************
- * This file is part of AndroidIDE.
- *
- *
+ * 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
@@ -36,6 +34,7 @@ import androidx.core.view.GravityCompat;
import com.itsaky.androidide.ui.inflater.IResourceFinder;
import com.itsaky.androidide.ui.view.IAttribute;
import com.itsaky.androidide.ui.view.IAttributeAdapter;
+import com.itsaky.androidide.utils.Logger;
import java.io.File;
import java.lang.reflect.Field;
import java.util.regex.Pattern;
@@ -47,34 +46,40 @@ public class BaseViewAttrAdapter implements IAttributeAdapter {
private final Pattern HEX_COLOR = Pattern.compile("#[a-fA-F0-9]{6,8}");
+ protected static final Logger LOG = Logger.instance ("BaseViewAttrAdapter");
public static final int ENUM_NOT_FOUND = -4116;
@Override
public boolean isApplicableTo(View view) {
- return true;
+ return true; // Can be applied to any view
}
@Override
public boolean apply(IAttribute attribute, View view, IResourceFinder resFinder) {
final String namespace = attribute.getNamespace();
- final String name = attribute.getNamespace();
+ final String name = attribute.getAttributeName();
final String value = attribute.getValue();
final ViewGroup.LayoutParams params = view.getLayoutParams();
final Resources res = view.getResources();
final DisplayMetrics dm = res.getDisplayMetrics();
final Context ctx = view.getContext();
- if (canHandleNamespace(namespace)) {
+ if (!canHandleNamespace(namespace)) {
+ LOG.error("Cannot handle namespace: " + namespace);
return false;
}
+ LOG.debug ("Adding attribute", attribute);
+
boolean handled = true;
switch (name) {
case "layout_height" :
params.height = parseDimension (value, -2, dm, resFinder);
+ LOG.error("Added layout_height", params.height);
break;
case "layout_width" :
params.width = parseDimension (value, -2, dm, resFinder);
+ LOG.error("Added layout_width", params.width);
break;
case "alpha" :
view.setAlpha(parseFloat(value));
@@ -221,33 +226,12 @@ public class BaseViewAttrAdapter implements IAttributeAdapter {
break;
}
- // In case these attributes are related to margins
- // We need to apply them by casting the params to ViewGroup.MarginLayoutParams
- if (!handled && params instanceof ViewGroup.MarginLayoutParams) {
- ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) params;
- switch (name) {
- case "layout_margin" :
- final int margin = parseDimension(value, 0, dm, resFinder);
- marginParams.setMargins(margin, margin, margin, margin);
- break;
- case "layout_marginLeft" :
- marginParams.leftMargin = parseDimension(value, 0, dm, resFinder);
- break;
- case "layout_marginTop" :
- marginParams.topMargin = parseDimension(value, 0, dm, resFinder);
- break;
- case "layout_marginRight" :
- marginParams.rightMargin = parseDimension(value, 0, dm, resFinder);
- break;
- case "layout_marginBottom" :
- marginParams.bottomMargin = parseDimension(value, 0, dm, resFinder);
- break;
- case "layout_marginStart" :
- marginParams.setMarginStart(parseDimension(value, 0, dm, resFinder));
- break;
- case "layout_marginEnd" :
- marginParams.setMarginEnd(parseDimension(value, 0, dm, resFinder));
- break;
+ // ----- Handle attributes related to parent ------
+ if (!handled) {
+
+ // Layout Margins
+ if (params instanceof ViewGroup.MarginLayoutParams) {
+ handleMarginParams((ViewGroup.MarginLayoutParams) params, name, value, dm, resFinder);
}
}
@@ -255,6 +239,33 @@ public class BaseViewAttrAdapter implements IAttributeAdapter {
return handled;
}
+
+ private void handleMarginParams(ViewGroup.MarginLayoutParams params, String name, String value, DisplayMetrics dm, IResourceFinder resFinder) {
+ switch (name) {
+ case "layout_margin" :
+ final int margin = parseDimension(value, 0, dm, resFinder);
+ params.setMargins(margin, margin, margin, margin);
+ break;
+ case "layout_marginLeft" :
+ params.leftMargin = parseDimension(value, 0, dm, resFinder);
+ break;
+ case "layout_marginTop" :
+ params.topMargin = parseDimension(value, 0, dm, resFinder);
+ break;
+ case "layout_marginRight" :
+ params.rightMargin = parseDimension(value, 0, dm, resFinder);
+ break;
+ case "layout_marginBottom" :
+ params.bottomMargin = parseDimension(value, 0, dm, resFinder);
+ break;
+ case "layout_marginStart" :
+ params.setMarginStart(parseDimension(value, 0, dm, resFinder));
+ break;
+ case "layout_marginEnd" :
+ params.setMarginEnd(parseDimension(value, 0, dm, resFinder));
+ break;
+ }
+ }
protected boolean canHandleNamespace(String namespace) {
// TODO Compare namespace URI instead of name
@@ -428,7 +439,7 @@ public class BaseViewAttrAdapter implements IAttributeAdapter {
case "drawable" :
return ContextCompat.getDrawable(ctx, id);
default :
- return newTransparentDrawable();
+ return newTransparentDrawable();
}
}
@@ -462,7 +473,9 @@ public class BaseViewAttrAdapter implements IAttributeAdapter {
if (HEX_COLOR.matcher(color).matches()) {
try {
return Color.parseColor(color);
- } catch (Throwable th) {}
+ } catch (Throwable th) {
+ // Ignored
+ }
} else if (color.startsWith("@color/")) {
return parseColor(resFinder.findColor(color.substring("@color/".length())), resFinder, ctx);
} else if (color.startsWith("@android:color/")) {
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewGroupAttrAdapter.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewGroupAttrAdapter.java
index 67c305069..8b8b9acbd 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewGroupAttrAdapter.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/BaseViewGroupAttrAdapter.java
@@ -43,7 +43,7 @@ public class BaseViewGroupAttrAdapter extends BaseViewAttrAdapter {
}
final ViewGroup group = (ViewGroup) view;
final String namespace = attribute.getNamespace();
- final String name = attribute.getNamespace();
+ final String name = attribute.getAttributeName();
final String value = attribute.getValue();
if (!canHandleNamespace(namespace)) {
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/ButtonAttrAdapter.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/ButtonAttrAdapter.java
index ec02311fe..987cf4966 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/ButtonAttrAdapter.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/ButtonAttrAdapter.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/LinearLayoutAttrAdapter.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/LinearLayoutAttrAdapter.java
index 17f709291..8f9e43777 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/LinearLayoutAttrAdapter.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/LinearLayoutAttrAdapter.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -43,7 +41,7 @@ public class LinearLayoutAttrAdapter extends BaseViewGroupAttrAdapter {
final LinearLayout linear = (LinearLayout) view;
final String namespace = attribute.getNamespace();
- final String name = attribute.getNamespace();
+ final String name = attribute.getAttributeName();
final String value = attribute.getValue();
if (!canHandleNamespace(namespace)) {
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/TextViewAttrAdapter.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/TextViewAttrAdapter.java
index 7b582e5a2..8bbceebd7 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/TextViewAttrAdapter.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/adapters/TextViewAttrAdapter.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -50,7 +48,7 @@ public class TextViewAttrAdapter extends BaseViewAttrAdapter {
final TextView text = (TextView) view;
final String namespace = attribute.getNamespace();
- final String name = attribute.getNamespace();
+ final String name = attribute.getAttributeName();
final String value = attribute.getValue();
final ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
final Resources res = view.getResources();
@@ -59,7 +57,7 @@ public class TextViewAttrAdapter extends BaseViewAttrAdapter {
final Drawable[] drawables = text.getCompoundDrawables();
final Drawable[] drawablesRelative = text.getCompoundDrawablesRelative();
- if (canHandleNamespace(namespace)) {
+ if (!canHandleNamespace(namespace)) {
return false;
}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseView.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseView.java
index 17fd1aae2..3ad52e1a8 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseView.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseView.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -29,10 +27,11 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.Objects;
public abstract class BaseView implements IView {
- protected final List attributes = new ArrayList<>();
+ protected final Set attributes = new HashSet<>();
protected final Set attrAdapters = new HashSet<>();
protected final String qualifiedName;
@@ -83,14 +82,13 @@ public abstract class BaseView implements IView {
this.attributes.add(attr);
for (IAttributeAdapter adapter : attrAdapters) {
- if (adapter.isApplicableTo(asView())) {
- if (adapter.apply(attr, asView(), resFinder)) {
+ if (adapter.isApplicableTo(asView())
+ && adapter.apply(attr, asView(), resFinder)) {
break;
- }
}
}
}
-
+
@Override
public void removeAttribute(IAttribute attr) {
this.attributes.remove(attr);
@@ -121,16 +119,18 @@ public abstract class BaseView implements IView {
return false;
}
- if (obj instanceof IView) {
- IView that = (IView) obj;
- return this.asView().equals(that.asView());
- }
-
- return false;
+ return this.hashCode() == obj.hashCode();
}
@Override
public int hashCode() {
- return asView().hashCode();
+ return Objects.hash(
+ attributes,
+ attrAdapters,
+ qualifiedName,
+ view,
+ parent,
+ isPlaceholder
+ );
}
}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseViewGroup.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseViewGroup.java
index 2c4e056d8..239cf839e 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseViewGroup.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/BaseViewGroup.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiAttribute.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiAttribute.java
index 3b9c8c9fd..e47321003 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiAttribute.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiAttribute.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
@@ -24,6 +22,7 @@ import com.itsaky.androidide.ui.view.IAttribute;
import com.itsaky.androidide.ui.view.IFixedValue;
import java.util.HashSet;
import java.util.Set;
+import java.util.Objects;
public class UiAttribute implements IAttribute {
@@ -76,18 +75,14 @@ public class UiAttribute implements IAttribute {
@Override
public boolean equals(Object obj) {
- if (obj instanceof UiAttribute) {
- UiAttribute that = (UiAttribute) obj;
- return this.getNamespace().equals(that.getNamespace())
- && this.getAttributeName().equals(that.getAttributeName())
- && this.getValue().equals(that.getValue())
- && this.getFixedValues().equals(that.getFixedValues());
+ if (obj == null) {
+ return false;
}
- return false;
+ return this.hashCode() == obj.hashCode();
}
@Override
public int hashCode() {
- return toString().hashCode();
+ return Objects.hash(namespace, name, value, fixedValues);
}
}
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiView.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiView.java
index d7d7bc560..e004afbc8 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiView.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiView.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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
diff --git a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiViewGroup.java b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiViewGroup.java
index 86b6b2fb7..61c436a38 100644
--- a/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiViewGroup.java
+++ b/layout-inflater/src/main/java/com/itsaky/androidide/ui/view/impl/UiViewGroup.java
@@ -1,8 +1,6 @@
/************************************************************************************
* 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