attributes) {
- attributes.removeIf(attr -> this.selectedView.hasAttribute(attr.namespace, attr.name));
- return new ArrayList<>(attributes);
- }
-
- @NonNull
- private AttributeListSheet getAttrListSheet() {
- if (mAttrListSheet == null) {
- mAttrListSheet = new AttributeListSheet();
- mAttrListSheet.setCancelable(true);
- }
-
- return mAttrListSheet;
- }
-
- @Override
- public void accept(Attr attr) {
- addNewAttribute(attr);
- }
-
- private void addNewAttribute(@NonNull Attr attr) {
- final XMLAttribute attribute = new XMLAttribute(attr.namespace, attr.name, "", false);
- attribute.setAttr(attr);
- showValueEditorSheet(attribute);
- }
-
- @Override
- public void onValueChanged(@NonNull IAttribute attribute, String newValue) {
- if (dismissIfSelectedNull()) {
- LOG.warn("Cannot update attribute with new value. Selected view is null.");
- return;
- }
-
- final var attributeName = attribute.getAttributeName();
- final var namespace = attribute.getNamespace();
-
- if (this.selectedView.hasAttribute(namespace, attributeName)) {
- this.selectedView.updateAttribute(namespace, attributeName, newValue);
- } else {
- final var attr = new UiAttribute(namespace, attributeName, newValue);
- this.selectedView.addAttribute(attr);
- }
- }
-
- /**
- * A listener can be used to get notified when we fail to remove a view from its parent. This is
- * used in {@link com.itsaky.androidide.DesignerActivity DesignerActivity}.
- *
- * When the user tries to remove the outermost view of the inflated layout, AttrEditorSheet
- * fails to remove the view from its parent ({@link IView#getParent()} is null for root XML
- * layout). In this case, DesignerActivity check if the view that we were trying to delete is the
- * root layout or not. If it is the root layout, then it deletes the layout from the layout
- * container.
- *
- * @author Akash Yadav
- */
- public interface OnViewDeletionFailedListener {
-
- /**
- * @param view The view that was not removed from its parent.
- * @return {@code true} if the listener handled the error. {@code false} otherwise.
- */
- boolean onDeletionFailed(IView view);
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrValueEditorSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrValueEditorSheet.java
deleted file mode 100644
index 04ee44b01..000000000
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrValueEditorSheet.java
+++ /dev/null
@@ -1,192 +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.fragments.sheets;
-
-import static com.itsaky.attrinfo.models.Attr.FORMAT_BOOLEAN;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_COLOR;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_DIMENSION;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_ENUM;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_FLAG;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_FLOAT;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_FRACTION;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_INTEGER;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_REFERENCE;
-import static com.itsaky.attrinfo.models.Attr.FORMAT_STRING;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
-import com.itsaky.androidide.adapters.AttrValueFormatTabAdapter;
-import com.itsaky.androidide.databinding.LayoutAttrValueEditorBinding;
-import com.itsaky.androidide.fragments.attr.BaseValueEditorFragment;
-import com.itsaky.androidide.fragments.attr.BooleanEditor;
-import com.itsaky.androidide.fragments.attr.ColorEditor;
-import com.itsaky.androidide.fragments.attr.DimensionEditor;
-import com.itsaky.androidide.fragments.attr.EnumEditor;
-import com.itsaky.androidide.fragments.attr.FlagEditor;
-import com.itsaky.androidide.fragments.attr.FloatEditor;
-import com.itsaky.androidide.fragments.attr.FractionEditor;
-import com.itsaky.androidide.fragments.attr.IntegerEditor;
-import com.itsaky.androidide.fragments.attr.ReferenceEditor;
-import com.itsaky.androidide.fragments.attr.StringEditor;
-import com.itsaky.androidide.models.XMLAttribute;
-import com.itsaky.attrinfo.models.Attr;
-import com.itsaky.inflater.IAttribute;
-
-import org.jetbrains.annotations.Contract;
-
-import java.util.Objects;
-
-/**
- * Sheet for editing value of an attribute.
- *
- * @author Akash Yadav
- */
-public class AttrValueEditorSheet extends BottomSheetDialogFragment
- implements BaseValueEditorFragment.OnValueChangeListener {
-
- private static final String KEY_ATTRIBUTE = "attrEditorSheet_attribute";
- private BaseValueEditorFragment.OnValueChangeListener valueChangeListener;
- private LayoutAttrValueEditorBinding binding;
- private AttrValueFormatTabAdapter adapter;
- private XMLAttribute attribute;
-
- @NonNull
- public static AttrValueEditorSheet newInstance(final XMLAttribute attribute) {
- Objects.requireNonNull(attribute);
-
- final var args = new Bundle();
- args.putParcelable(KEY_ATTRIBUTE, attribute);
-
- final var fragment = new AttrValueEditorSheet();
- fragment.setArguments(args);
- return fragment;
- }
-
- @Override
- public void onAttach(@NonNull Context context) {
- super.onAttach(context);
- this.valueChangeListener = (BaseValueEditorFragment.OnValueChangeListener) getParentFragment();
- }
-
- @Nullable
- @Override
- public View onCreateView(
- @NonNull LayoutInflater inflater,
- @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- this.binding = LayoutAttrValueEditorBinding.inflate(inflater, container, false);
- return binding.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- if (attribute == null) {
- this.attribute = requireArguments().getParcelable(KEY_ATTRIBUTE);
- }
-
- Objects.requireNonNull(this.attribute);
-
- final var namespace = this.attribute.getNamespace();
- final var formatText = Attr.createFormatText(attribute.getFormat());
- this.binding.attributeName.setText(
- String.format("%s:%s", namespace.getPrefix(), attribute.getAttributeName()));
- this.binding.attributeFormat.setText(formatText);
-
- setupTabs(formatText);
- }
-
- @SuppressLint("NotifyDataSetChanged")
- private void setupTabs(@NonNull String formatText) {
- this.binding.tabs.removeAllTabs();
- this.binding.pager.setSaveEnabled(false);
-
- if (this.adapter != null) {
- this.adapter.removeAll();
- this.adapter.notifyDataSetChanged();
- }
-
- this.adapter = new AttrValueFormatTabAdapter(getChildFragmentManager(), attribute);
-
- final var formats = formatText.split("\\|");
- for (var formatName : formats) {
- if (TextUtils.isEmpty(formatName) || formatName.length() < 2) {
- continue;
- }
-
- final var frag = getFragmentClass(formatName);
- if (frag != null) {
- this.adapter.addFragment(frag, formatName);
- }
- }
-
- binding.pager.setAdapter(this.adapter);
- binding.tabs.setupWithViewPager(binding.pager);
- }
-
- @Nullable
- @Contract(pure = true)
- private Class extends BaseValueEditorFragment> getFragmentClass(@NonNull String name) {
- switch (name) {
- case FORMAT_REFERENCE:
- return ReferenceEditor.class;
- case FORMAT_COLOR:
- return ColorEditor.class;
- case FORMAT_BOOLEAN:
- return BooleanEditor.class;
- case FORMAT_DIMENSION:
- return DimensionEditor.class;
- case FORMAT_FLOAT:
- return FloatEditor.class;
- case FORMAT_INTEGER:
- return IntegerEditor.class;
- case FORMAT_FRACTION:
- return FractionEditor.class;
- case FORMAT_STRING:
- return StringEditor.class;
- case FORMAT_ENUM:
- return EnumEditor.class;
- case FORMAT_FLAG:
- return FlagEditor.class;
- }
-
- return null;
- }
-
- public void setAttribute(XMLAttribute attribute) {
- Objects.requireNonNull(attribute);
- this.attribute = attribute;
- }
-
- @Override
- public void onValueChanged(IAttribute attribute, String newValue) {
- if (valueChangeListener != null) {
- valueChangeListener.onValueChanged(attribute, newValue);
- }
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java
deleted file mode 100644
index f6a8e6c66..000000000
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java
+++ /dev/null
@@ -1,132 +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.fragments.sheets;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.widget.SearchView;
-import androidx.fragment.app.DialogFragment;
-
-import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
-import com.itsaky.androidide.resources.R;
-import com.itsaky.androidide.adapters.AttrListAdapter;
-import com.itsaky.androidide.databinding.LayoutAddAttrSheetBinding;
-import com.itsaky.attrinfo.models.Attr;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-/**
- * A bottom sheet dialog for showing a simple list of text icon pair.
- *
- * @author Akash Yadav
- * @see com.itsaky.androidide.models.IconTextListItem
- */
-public class AttributeListSheet extends BottomSheetDialogFragment {
-
- private LayoutAddAttrSheetBinding binding;
- private Consumer clickConsumer;
- private List mItems;
-
- @Nullable
- @Override
- public View onCreateView(
- @NonNull LayoutInflater inflater,
- @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- this.binding = LayoutAddAttrSheetBinding.inflate(inflater, container, false);
- return binding.getRoot();
- }
-
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- binding.searchBar.setOnQueryTextListener(
- new SearchView.OnQueryTextListener() {
-
- @Override
- public boolean onQueryTextSubmit(String query) {
- return filterAttributes(query.trim());
- }
-
- @Override
- public boolean onQueryTextChange(String newText) {
- return filterAttributes(newText.trim());
- }
- });
- binding.attrList.setAdapter(new AttrListAdapter(clickConsumer, mItems));
- }
-
- private boolean filterAttributes(@NonNull String query) {
- if (mItems == null || TextUtils.isEmpty(query)) {
- update();
- return true;
- }
-
- final var filtered =
- this.mItems.stream()
- .filter(
- attr -> attr.name.toLowerCase(Locale.ROOT).contains(query.toLowerCase(Locale.ROOT)))
- .collect(Collectors.toList());
-
- update(filtered);
- return true;
- }
-
- public void update() {
- update(mItems);
- }
-
- public void update(List items) {
- if (binding != null) {
- binding.attrList.setAdapter(new AttrListAdapter(clickConsumer, items));
- }
- }
-
- public void setItems(@Nullable List items) {
- if (items == null) {
- items = new ArrayList<>();
- }
-
- mItems = items;
- update();
- }
-
- @Override
- public void onAttach(@NonNull Context context) {
- super.onAttach(context);
- //noinspection unchecked
- this.clickConsumer = (Consumer) getParentFragment();
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setStyle(DialogFragment.STYLE_NORMAL, R.style.AppTheme_SheetAboveKeyboard);
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/language/xml/XMLAnalyzer.kt b/app/src/main/java/com/itsaky/androidide/language/xml/XMLAnalyzer.kt
index 81ee3dbe1..0f620f173 100644
--- a/app/src/main/java/com/itsaky/androidide/language/xml/XMLAnalyzer.kt
+++ b/app/src/main/java/com/itsaky/androidide/language/xml/XMLAnalyzer.kt
@@ -18,8 +18,8 @@
package com.itsaky.androidide.language.xml
import android.graphics.Color
+import android.graphics.Color.parseColor
import com.google.common.collect.EvictingQueue
-import com.itsaky.androidide.app.IDEApplication
import com.itsaky.androidide.language.incremental.BaseIncrementalAnalyzeManager
import com.itsaky.androidide.language.incremental.IncrementalToken
import com.itsaky.androidide.language.incremental.LineState
@@ -48,10 +48,10 @@ import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.OPERATOR
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.TEXT_NORMAL
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.XML_TAG
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forComment
-import com.itsaky.inflater.util.CommonParseUtils
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle.makeStyle
+import java.util.regex.Pattern
/**
* Syntax analyzer for XML.
@@ -85,7 +85,7 @@ class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
override fun popTokensAfterIncomplete(
incompleteToken: IncrementalToken,
- tokens: MutableList
+ tokens: MutableList,
) {
// Do nothing
}
@@ -93,8 +93,6 @@ class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
override fun generateSpans(
tokens: LineTokenizeResult,
): MutableList {
- val app = IDEApplication.getInstance()
- val parser = CommonParseUtils(app.resourceTable, app.resources.displayMetrics)
val spans = mutableListOf()
var previous = XMLLexer.SEA_WS
@@ -109,7 +107,7 @@ class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
COMMENT_START,
COMMENT_END,
CommentModeEnd,
- CommentText -> spans.add(Span.obtain(offset, forComment()))
+ CommentText, -> spans.add(Span.obtain(offset, forComment()))
OPEN,
DASH,
NOT,
@@ -126,8 +124,7 @@ class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
val text: String = token.text
val textVar = text.replace("\"", "")
if (isColorValue(textVar)) {
- val color: Int =
- parser.parseColor(textVar, IDEApplication.getInstance().applicationContext)
+ val color: Int = parseColor(textVar)
val span = Span.obtain(offset + 1, makeStyle(LITERAL))
span.setUnderlineColor(color)
spans.add(span)
@@ -163,8 +160,7 @@ class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
try {
val textVar: String = token.text
if (isColorValue(textVar)) {
- val color: Int =
- parser.parseColor(textVar, IDEApplication.getInstance().applicationContext)
+ val color: Int = parseColor(textVar)
val span = Span.obtain(offset, makeStyle(TEXT_NORMAL))
span.setUnderlineColor(color)
spans.add(span)
@@ -187,8 +183,7 @@ class XMLAnalyzer : BaseIncrementalAnalyzeManager(XMLLexer::class.java) {
override fun handleIncompleteToken(token: IncrementalToken) {}
private fun isColorValue(value: String): Boolean {
- return (value.startsWith("#") ||
- value.startsWith("@android:color") ||
- value.startsWith("@color/"))
+ return hexColorMatcher.matcher(value).matches()
}
+ private val hexColorMatcher: Pattern = Pattern.compile("#[a-fA-F\\d]{6,8}")
}
diff --git a/app/src/main/java/com/itsaky/androidide/models/UIWidget.java b/app/src/main/java/com/itsaky/androidide/models/UIWidget.java
deleted file mode 100755
index 4b38c34d7..000000000
--- a/app/src/main/java/com/itsaky/androidide/models/UIWidget.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.models;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.View;
-
-import androidx.annotation.DrawableRes;
-
-import java.util.Objects;
-
-/**
- * Holds data about the widget item in widgets list shown in UI Designer screen.
- *
- * @author Akash Yadav
- */
-public class UIWidget implements IconTextListItem, Parcelable {
-
- public static final Creator CREATOR =
- new Creator() {
- @Override
- public UIWidget createFromParcel(Parcel in) {
- return new UIWidget(in);
- }
-
- @Override
- public UIWidget[] newArray(int size) {
- return new UIWidget[size];
- }
- };
- private final String name;
- private final int icon;
- private final String clazz;
-
- private UIWidget(Parcel in) {
- this.name = in.readString();
- this.icon = in.readInt();
- this.clazz = in.readString();
- }
-
- public UIWidget(String name, @DrawableRes int icon, Class> clazz) {
- this.name = name;
- this.icon = icon;
- this.clazz = clazz.getName();
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getName(), getIcon(), clazz);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- UIWidget widget = (UIWidget) o;
- return getIcon() == widget.getIcon()
- && getName().equals(widget.getName())
- && clazz.equals(widget.clazz);
- }
-
- public String getName() {
- return name;
- }
-
- public int getIcon() {
- return icon;
- }
-
- /**
- * Get the class of this widget.
- *
- * @return The class that this widget represents
- * @throws ClassNotFoundException If there is no class with this widget's class name. However,
- * this will never be thrown.
- */
- public Class extends View> asClass() throws ClassNotFoundException {
- return getClass().getClassLoader().loadClass(this.clazz).asSubclass(View.class);
- }
-
- public String getWidgetClassName() {
- return this.clazz;
- }
-
- @Override
- public String getText() {
- return getName();
- }
-
- @Override
- public int getIconResource() {
- return getIcon();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(name);
- dest.writeInt(icon);
- dest.writeString(clazz);
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java b/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java
deleted file mode 100755
index fa1fb3b0a..000000000
--- a/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java
+++ /dev/null
@@ -1,165 +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.models;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import androidx.annotation.NonNull;
-
-import org.jetbrains.annotations.Contract;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Model class for holding data about a group that will be displayed in Widgets list in UI Designer
- * screen.
- *
- * A UIWidgetGroup contains multiple {@link UIWidget}.
- *
- * @author Akash Yadav
- */
-public class UIWidgetGroup implements IconTextListItem, Parcelable {
-
- public static final Creator CREATOR =
- new Creator() {
-
- @NonNull
- @Contract("_ -> new")
- @Override
- public UIWidgetGroup createFromParcel(Parcel in) {
- return new UIWidgetGroup(in);
- }
-
- @NonNull
- @Contract(value = "_ -> new", pure = true)
- @Override
- public UIWidgetGroup[] newArray(int size) {
- return new UIWidgetGroup[size];
- }
- };
- /** Name of this group. */
- private final String name;
- /** Children of this group. */
- private final List children;
- /** Is this group currently selected in the group list? */
- private boolean selected;
-
- public UIWidgetGroup(String name) {
- this.name = name;
- this.selected = false;
- this.children = new ArrayList<>();
- }
-
- protected UIWidgetGroup(@NonNull Parcel in) {
- this.name = in.readString();
- this.children = in.createTypedArrayList(UIWidget.CREATOR);
- this.selected = in.readByte() != 0;
- }
-
- /**
- * Add this widget to this group. Does nothing if the child is already present.
- *
- * @param child The child to add.
- * @return This instance for chained method calls.
- */
- public UIWidgetGroup addChild(UIWidget child) {
- if (children.contains(child)) {
- return this;
- }
- this.children.add(child);
- return this;
- }
-
- /**
- * Get the child at the given index.
- *
- * @param index The index of the child.
- * @return The child at the index.
- * @throws IndexOutOfBoundsException If the given index is not valid.
- */
- public UIWidget getChild(int index) {
- return children.get(index);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getName(), getChildren(), isSelected());
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- UIWidgetGroup group = (UIWidgetGroup) o;
- return isSelected() == group.isSelected()
- && getName().equals(group.getName())
- && getChildren().equals(group.getChildren());
- }
-
- /**
- * Get the name of this group.
- *
- * @return The name of this group.
- */
- public String getName() {
- return name;
- }
-
- /**
- * Get the children of this group.
- *
- * @return The children.
- */
- @NonNull
- public List getChildren() {
- return children;
- }
-
- public boolean isSelected() {
- return selected;
- }
-
- public void setSelected(boolean selected) {
- this.selected = selected;
- }
-
- @Override
- public String getText() {
- return getName();
- }
-
- @Override
- public int getIconResource() {
- return -1;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(name);
- dest.writeTypedList(children);
- dest.writeByte((byte) (selected ? 1 : 0));
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java b/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
deleted file mode 100644
index 885538fc1..000000000
--- a/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
+++ /dev/null
@@ -1,178 +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.models;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.androidide.app.IDEApplication;
-import com.itsaky.attrinfo.models.Attr;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.impl.UiAttribute;
-import com.itsaky.xml.INamespace;
-
-import org.jetbrains.annotations.Contract;
-
-import java.util.Objects;
-
-/**
- * A model that is used to show attributes list of a view.
- *
- * @author Akash Yadav
- */
-public class XMLAttribute extends UiAttribute implements Parcelable {
-
- public static final Creator CREATOR =
- new Creator<>() {
- @NonNull
- @Contract("_ -> new")
- @Override
- public XMLAttribute createFromParcel(Parcel in) {
- return new XMLAttribute(in);
- }
-
- @NonNull
- @Contract(value = "_ -> new", pure = true)
- @Override
- public XMLAttribute[] newArray(int size) {
- return new XMLAttribute[size];
- }
- };
- public Attr attr;
- /** Is this attribute applied to any view? */
- private boolean isApplied;
- /**
- * Format of this attribute. May be stored here so we don't have to look in {@link
- * com.itsaky.attrinfo.AttrInfo AttrInfo} again and again.
- */
- private int format = -1;
-
- public XMLAttribute(IAttribute attribute) {
- this(attribute, true);
- }
-
- public XMLAttribute(@NonNull IAttribute attribute, boolean isApplied) {
- this(attribute.getNamespace(), attribute.getAttributeName(), attribute.getValue(), isApplied);
- }
-
- public XMLAttribute(INamespace namespace, String name, String value, boolean isApplied) {
- super(namespace, name, value);
- this.isApplied = isApplied;
- }
-
- private XMLAttribute(@NonNull Parcel in) {
- this(
- in.readParcelable(INamespace.class.getClassLoader()),
- in.readString(),
- in.readString(),
- in.readByte() != 0);
- this.attr = in.readParcelable(Attr.class.getClassLoader());
- this.format = in.readInt();
- }
-
- /**
- * Create a new attribute instance with the android namespace. {@link #isApplied()} will return
- * true by default.
- *
- * @param name The name of the attribute.
- * @param value The value of the attribute.
- * @return A new instance of this class with the provided data.
- */
- @NonNull
- @Contract("_, _ -> new")
- public static XMLAttribute newAndroidAttribute(String name, String value) {
- return new XMLAttribute(INamespace.ANDROID, name, value, true);
- }
-
- /**
- * Create a new attribute instance with the android namespace. The {@link #isApplied()} will
- * return {@code false} by default.
- *
- * @param name The name of the attribute.
- * @return The new attribute instance.
- */
- @NonNull
- @Contract("_ -> new")
- public static XMLAttribute newAndroidAttribute(String name) {
- return new XMLAttribute(INamespace.ANDROID, name, "", false);
- }
-
- public int findFormat() {
-
- if (getFormat() > 0) {
- return getFormat();
- }
-
- final var attrs = IDEApplication.getInstance().attrInfo();
- this.attr = attrs.getAttribute(getAttributeName());
- if (this.attr != null) {
- this.format = this.attr.format;
- }
-
- return getFormat();
- }
-
- public int getFormat() {
- return format;
- }
-
- public void setFormat(int format) {
- this.format = format;
- }
-
- public boolean hasFormat(int format) {
- return (this.format & format) != 0;
- }
-
- @Override
- public void apply(String value) {
- super.apply(value);
- isApplied = true;
- }
-
- public boolean isApplied() {
- return isApplied;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(getNamespace(), flags);
- dest.writeString(getAttributeName());
- dest.writeString(getValue());
- dest.writeByte((byte) (isApplied ? 1 : 0));
- dest.writeParcelable(getAttr(), flags);
- dest.writeInt(this.format);
- }
-
- public Attr getAttr() {
- return attr;
- }
-
- public void setAttr(Attr attr) {
- Objects.requireNonNull(attr);
- this.attr = attr;
- setFormat(attr.format);
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java b/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java
deleted file mode 100644
index 102b107e0..000000000
--- a/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java
+++ /dev/null
@@ -1,312 +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.projects;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.values.ValuesTableFactory;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Locale;
-
-public class ProjectResourceTable implements IResourceTable {
-
- private static final ILogger LOG = ILogger.newInstance("ProjectResourceFinder");
- private File resDir;
- private File color;
- private File layout;
- private File[] drawables;
- private File[] mipmaps;
-
- @Override
- public File findDrawable(@NonNull String name) {
- for (File drawable : drawables) {
- final File file = findFileWithName(drawable.listFiles(), name);
- if (file != null) {
- return file;
- }
- }
-
- return null;
- }
-
- @Override
- public File findLayout(@NonNull String name) {
- return findFileWithName(this.layout.listFiles(), name);
- }
-
- @Override
- public String findString(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findString(name);
- if (resource == null) {
- return name;
- }
-
- final var value = resource.getValue();
- if (value.startsWith("@string/")) {
- var ref = value.substring("@string/".length());
- if (name.equals(ref)) {
- return name;
- }
- }
-
- return value;
- }
-
- @Override
- public String findColor(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findColor(name);
- if (resource == null) {
- return name;
- }
-
- final var value = resource.getValue();
- if (value.startsWith("@color/")) {
- var ref = value.substring("@color/".length());
- if (name.equals(ref)) {
- return name;
- }
- }
-
- return value;
- }
-
- @Override
- public String[] findArray(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
- if (table == null) {
- return new String[] {name};
- }
-
- final var resource = table.findArray(name);
- if (resource == null) {
- return new String[] {name};
- }
-
- return resource.getValues();
- }
-
- @Override
- public String findDimension(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findDimension(name);
- if (resource == null) {
- return name;
- }
-
- final var value = resource.getValue();
- if (value.startsWith("@dimen/")) {
- var ref = value.substring("@dimen/".length());
- if (name.equals(ref)) {
- return name;
- }
- }
-
- return value;
- }
-
- @Override
- public String findBoolean(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findBoolean(name);
- if (resource == null) {
- return name;
- }
-
- final var val = resource.getValue();
- if (val.startsWith("@bool/")) {
- final var ref = val.substring("@bool/".length());
- if (ref.equals(name)) {
- // recursive reference
- return name;
- }
- }
-
- return val;
- }
-
- @Override
- public String findInteger(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findInteger(name);
- if (resource == null) {
- return name;
- }
-
- final var val = resource.getValue();
- if (val.startsWith("@integer/")) {
- final var ref = val.substring("@integer/".length());
- if (ref.equals(name)) {
- // recursive reference
- return name;
- }
- }
-
- return val;
- }
-
- @Override
- public void setInflatingFile(@NonNull File file) {
- if (file.getParentFile() == null) {
- throw new IllegalArgumentException("Invalid inflating file");
- }
-
- setupDirectories(
- file // layout file
- .getParentFile() // layout dir
- .getParentFile()); // res dir
- }
-
- @NonNull
- @Override
- public Collection listResourceNames(@Nullable String type) {
- if (type == null) {
- return listAllResourceNames();
- } else {
- final var set = new HashSet();
- switch (type) {
- case "drawable":
- for (var folder : this.drawables) {
- listAndAddTo(set, folder, type);
- }
- break;
- case "layout":
- listAndAddTo(set, this.layout, type);
- break;
- case "color":
- listAndAddTo(set, this.color, type);
- break;
- case "mipmap":
- for (var folder : this.mipmaps) {
- listAndAddTo(set, folder, type);
- }
- break;
- }
-
- return set;
- }
- }
-
- private void setupDirectories(File resDir) {
-
- if (resDir == null) {
- LOG.error("Null resource directory passed to resource finder. Ignoring.");
- return;
- }
-
- this.resDir = resDir;
- this.color = new File(resDir, "color");
- this.layout = new File(resDir, "layout");
-
- final File[] drawables = resDir.listFiles(new NameStartsWith("drawable"));
- this.drawables = drawables == null ? new File[0] : drawables;
-
- final File[] mipmaps = resDir.listFiles(new NameStartsWith("mipmap"));
- this.mipmaps = mipmaps == null ? new File[0] : mipmaps;
- }
-
- private File findFileWithName(File[] files, String name) {
- if (files == null || name == null) {
- return null;
- }
-
- for (File file : files) {
- var simpleName = file.getName();
-
- if (simpleName.startsWith(name)) {
- return file;
- }
- }
-
- return null;
- }
-
- private void listAndAddTo(HashSet set, @NonNull File dir, String type) {
- final var files = dir.listFiles();
- if (files == null) {
- return;
- }
-
- for (var file : files) {
- var name = file.getName();
- if (!name.contains(".")) {
- continue;
- }
-
- name = name.substring(0, name.lastIndexOf('.'));
- name = String.format(Locale.ROOT, "@%s/%s", type, name);
- set.add(name);
- }
- }
-
- @NonNull
- private Collection listAllResourceNames() {
- final var set = new HashSet<>(listResourceNames("color"));
- set.addAll(listResourceNames("drawable"));
- set.addAll(listResourceNames("mipmap"));
- set.addAll(listResourceNames("layout"));
- return set;
- }
-
- private static class NameStartsWith implements FileFilter {
-
- private final String name;
-
- public NameStartsWith(String name) {
- this.name = name;
- }
-
- @Override
- public boolean accept(@NonNull File file) {
- return file.getName().startsWith(name);
- }
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/WidgetDragData.java b/app/src/main/java/com/itsaky/androidide/ui/WidgetDragData.java
deleted file mode 100755
index f61489793..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/WidgetDragData.java
+++ /dev/null
@@ -1,55 +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;
-
-import com.itsaky.androidide.models.UIWidget;
-import com.itsaky.inflater.IView;
-
-/**
- * Store data about a draggable widget. Used in UI Designer.
- *
- * @author Akash Yadav
- */
-public class WidgetDragData {
-
- /**
- * Set this to true if the view that is being dragged was already inflated in the layout. If this
- * is set to {@code true}, {@link #alreadyInflatedView} must NOT be {@code null}.
- *
- * If this is {@code false}, then {@link #newDragData} must be not be null.
- */
- public boolean isAlreadyInflated;
-
- /**
- * The view that was already inflated and is being relocated. This must not be null if {@link
- * #isAlreadyInflated} is {@code true}.
- */
- public IView alreadyInflatedView;
-
- /** The UIWidget that is being dragged. */
- public UIWidget newDragData;
-
- private WidgetDragData() {}
-
- public WidgetDragData(
- boolean isAlreadyInflated, IView alreadyInflatedView, UIWidget newDragData) {
- this.isAlreadyInflated = isAlreadyInflated;
- this.alreadyInflatedView = alreadyInflatedView;
- this.newDragData = newDragData;
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/WidgetDragListener.java b/app/src/main/java/com/itsaky/androidide/ui/WidgetDragListener.java
deleted file mode 100755
index 606b63e47..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/WidgetDragListener.java
+++ /dev/null
@@ -1,226 +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;
-
-import android.content.Context;
-import android.graphics.RectF;
-import android.view.DragEvent;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-
-import com.blankj.utilcode.util.SizeUtils;
-import com.itsaky.androidide.DesignerActivity;
-import com.itsaky.androidide.resources.R;
-import com.itsaky.androidide.models.UIWidget;
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IView;
-import com.itsaky.inflater.IViewGroup;
-import com.itsaky.inflater.impl.ErrorUiView;
-import com.itsaky.inflater.impl.UiAttribute;
-import com.itsaky.inflater.impl.UiView;
-import com.itsaky.inflater.impl.UiViewGroup;
-import com.itsaky.xml.INamespace;
-
-import org.jetbrains.annotations.Contract;
-
-/**
- * Common drag listener for handling drag events in all ViewGroups in the UI Designer.
- *
- * @author Akash Yadav
- */
-public class WidgetDragListener implements View.OnDragListener {
-
- public static final String ANDROID_NS = "android";
- private static final ILogger LOG = ILogger.newInstance("WidgetDragListener");
- private final IView placeholder;
- private final IViewGroup viewGroup;
- private final OnViewAddedListener addedListener;
- private final int PLACEHOLDER_HEIGHT = 20; // in dp
- private final int PLACEHOLDER_WIDTH = 40; // in dp
-
- public WidgetDragListener(
- @NonNull Context context, IViewGroup viewGroup, OnViewAddedListener addedListener) {
- this.placeholder = new UiView("android.view.View", new View(context), true);
- this.viewGroup = viewGroup;
- this.addedListener = addedListener;
- this.placeholder.asView().setBackgroundResource(R.drawable.bg_widget_drag_placeholder);
- this.placeholder
- .asView()
- .setLayoutParams(
- new ViewGroup.LayoutParams(
- SizeUtils.dp2px(PLACEHOLDER_WIDTH), SizeUtils.dp2px(PLACEHOLDER_HEIGHT)));
- }
-
- @Override
- public boolean onDrag(View v, @NonNull DragEvent event) {
-
- if (this.viewGroup instanceof ErrorUiView) {
- return false;
- }
-
- final var action = event.getAction();
- final var clipDesc = event.getClipDescription();
- final var dragData = (WidgetDragData) event.getLocalState();
-
- var handled = true;
- switch (action) {
- case DragEvent.ACTION_DRAG_STARTED:
- handled = clipDesc.hasMimeType(DesignerActivity.DRAGGING_WIDGET_MIME);
- break;
- case DragEvent.ACTION_DRAG_ENTERED:
- case DragEvent.ACTION_DRAG_LOCATION:
- this.placeholder.removeFromParent(); // If placeholder is added in another group, remove it.
- this.viewGroup.addView(this.placeholder, findPlaceHolderIndex(event.getX(), event.getY()));
- break;
- case DragEvent.ACTION_DRAG_EXITED:
- this.placeholder.removeFromParent();
- break;
- case DragEvent.ACTION_DROP:
- final var index = this.viewGroup.indexOfChild(this.placeholder);
- this.placeholder.removeFromParent();
-
- var view =
- dragData.isAlreadyInflated
- ? dragData.alreadyInflatedView
- : createView(dragData.newDragData);
- if (!dragData.isAlreadyInflated) {
- applyBasicAttributes(view);
- }
-
- // Remove from parent if it has a parent
- view.removeFromParent();
- this.viewGroup.addView(view, index);
-
- if (this.addedListener != null) {
- this.addedListener.onViewAdded(view);
- }
-
- break;
- }
-
- return handled;
- }
-
- private void applyBasicAttributes(@NonNull IView view) {
- view.addAttribute(layoutWidthAttr());
- view.addAttribute(layoutHeightAttr());
- }
-
- @NonNull
- @Contract(" -> new")
- private IAttribute layoutHeightAttr() {
- return new UiAttribute(INamespace.ANDROID, "layout_height", "wrap_content");
- }
-
- @NonNull
- @Contract(" -> new")
- private IAttribute layoutWidthAttr() {
- return new UiAttribute(INamespace.ANDROID, "layout_width", "wrap_content");
- }
-
- /**
- * Finds the index at which the placeholder will be added in the current view group.
- *
- * @param x The x coordinate of the touch event
- * @param y The y coordinate of the touch event
- * @return The index at which the placeholder of the view should be added. The returned index is
- * always valid index in the {@link #viewGroup}.
- */
- private int findPlaceHolderIndex(final float x, final float y) {
- final var count = this.viewGroup.getChildCount();
- for (int i = 0; i < this.viewGroup.getChildCount(); i++) {
- final var child = this.viewGroup.getChildAt(i);
- final var rect = getViewRect(child);
- if (rect.contains(x, y)) {
- final var top = topHalf(rect);
- final var bottom = bottomHalf(rect);
- if (top.contains(x, y)) {
- return Math.max(0, i - 1);
- } else if (bottom.contains(x, y)) {
- return Math.min(count, i + 1);
- }
- }
- }
-
- // If we don't find a suitable index, return the last index
- return count;
- }
-
- @NonNull
- private RectF getViewRect(@NonNull IView view) {
- final var v = view.asView();
-
- final var rect = new RectF();
- rect.left = v.getLeft();
- rect.top = v.getTop();
- rect.right = rect.left + v.getWidth();
- rect.bottom = rect.top + v.getHeight();
-
- return rect;
- }
-
- private RectF topHalf(RectF src) {
- final RectF result = new RectF(src);
- result.bottom -= result.height() / 2;
- return src;
- }
-
- private RectF bottomHalf(RectF src) {
- final RectF result = new RectF(src);
- result.top += result.height() / 2;
- return src;
- }
-
- @NonNull
- private IView createView(@NonNull UIWidget widget) {
- try {
- final var clazz = widget.asClass();
- final var constructor = clazz.getConstructor(Context.class);
- constructor.setAccessible(true);
- final var instance = constructor.newInstance(this.viewGroup.asView().getContext());
-
- if (instance instanceof ViewGroup) {
- return new UiViewGroup(clazz.getName(), (ViewGroup) instance);
- } else {
- return new UiView(clazz.getName(), instance);
- }
- } catch (Throwable e) {
- LOG.error("Unable to add widget", e);
- throw new RuntimeException("Unable to add widget", e);
- }
- }
-
- private RectF leftHalf(RectF src) {
- final RectF result = new RectF(src);
- result.right -= result.width() / 2;
- return src;
- }
-
- private RectF rightHalf(RectF src) {
- final RectF result = new RectF(src);
- result.left += result.width() / 2;
- return src;
- }
-
- public static interface OnViewAddedListener {
- void onViewAdded(IView view);
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/WidgetDragShadowBuilder.java b/app/src/main/java/com/itsaky/androidide/ui/WidgetDragShadowBuilder.java
deleted file mode 100755
index cc87c0d85..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/WidgetDragShadowBuilder.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;
-
-import android.graphics.Point;
-import android.view.View;
-
-public class WidgetDragShadowBuilder extends View.DragShadowBuilder {
-
- private final double TOUCH_Y_OFFSET = 0.3;
-
- public WidgetDragShadowBuilder(View view) {
- super(view);
- }
-
- @Override
- public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
- if (getView() != null) {
- final var width = getView().getWidth();
- final var height = getView().getHeight();
- outShadowSize.set(width, height);
- outShadowTouchPoint.set(width / 2, height + (int) (height * TOUCH_Y_OFFSET));
- } else {
- super.onProvideShadowMetrics(outShadowSize, outShadowTouchPoint);
- }
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java b/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java
deleted file mode 100644
index d45b6f1f8..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java
+++ /dev/null
@@ -1,110 +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;
-
-import android.annotation.SuppressLint;
-import android.view.GestureDetector;
-import android.view.HapticFeedbackConstants;
-import android.view.MotionEvent;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.inflater.IView;
-
-/**
- * A touch listener for handling touch events of a view in the UI Designer.
- *
- *
Some of the views have no effect of setting a click listener or a long click listener (e.g.
- * SeekBar). In order to fix this, we use {@link android.view.GestureDetector} and manually handle
- * click events.
- *
- * @author Akash Yadav
- */
-public class WidgetTouchListener extends GestureDetector.SimpleOnGestureListener
- implements View.OnTouchListener {
-
- private final GestureDetector mGestureDetector;
- private final OnClickListener clickListener;
- private final OnLongClickListener longClickListener;
-
- private final IView mView;
-
- public WidgetTouchListener(
- @NonNull IView view,
- @Nullable OnClickListener clickListener,
- @Nullable OnLongClickListener longClickListener) {
- this.mView = view;
- this.mGestureDetector = new GestureDetector(view.asView().getContext(), this);
- this.clickListener = clickListener;
- this.longClickListener = longClickListener;
- }
-
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouch(View view, @NonNull MotionEvent motionEvent) {
- return mGestureDetector.onTouchEvent(motionEvent);
- }
-
- // TODO Should we use onSingleTapConfirmed instead?
- @Override
- public boolean onSingleTapUp(MotionEvent e) {
- if (this.clickListener != null) {
- this.clickListener.onClick(this.mView);
- }
-
- return true;
- }
-
- @Override
- public void onLongPress(MotionEvent e) {
-
- if (this.mView.getParent() == null) {
- // This is the root layout so this should not be draggable
- return;
- }
-
- if (this.longClickListener != null && this.longClickListener.onLongClick(this.mView)) {
- this.mView.asView().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- }
- }
-
- @Override
- public boolean onDown(MotionEvent e) {
- return true; // We would like to get notified about further events.
- }
-
- /**
- * A listener which is invoked when we detect a single click event.
- *
- * @author Akash Yadav
- */
- public interface OnClickListener {
- void onClick(IView view);
- }
-
- /**
- * A listener which is invoked when we detect a long click event.
- *
- * @author Akash Yadav
- */
- public interface OnLongClickListener {
- boolean onLongClick(IView view);
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/edit/BaseSuggestionProvider.java b/app/src/main/java/com/itsaky/androidide/ui/edit/BaseSuggestionProvider.java
deleted file mode 100644
index 313074821..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/edit/BaseSuggestionProvider.java
+++ /dev/null
@@ -1,58 +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.edit;
-
-import com.itsaky.androidide.app.IDEApplication;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.values.ValuesTable;
-import com.itsaky.inflater.values.ValuesTableFactory;
-
-import java.io.File;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * Base class for attribute edit handlers.
- *
- * @author Akash Yadav
- */
-public abstract class BaseSuggestionProvider implements IValueSuggestionProvider {
-
- protected final File resDir;
- protected final File layout;
-
- protected BaseSuggestionProvider(File layout) {
- Objects.requireNonNull(layout);
-
- final var path = layout.getAbsolutePath();
- if (!Pattern.compile(".*/src/.*/res/layout/(\\w|_)+\\.xml").matcher(path).matches()) {
- throw new IllegalArgumentException("Given layout file is not valid");
- }
-
- this.layout = layout;
- this.resDir = Objects.requireNonNull(layout.getParentFile()).getParentFile();
- Objects.requireNonNull(this.resDir);
- }
-
- protected ValuesTable getValuesTable() {
- return ValuesTableFactory.getTable(this.resDir);
- }
-
- protected IResourceTable getResourceTable() {
- return IDEApplication.getInstance().getResourceTable();
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/edit/DimensionSuggestionProvider.java b/app/src/main/java/com/itsaky/androidide/ui/edit/DimensionSuggestionProvider.java
deleted file mode 100644
index d8ce3a3db..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/edit/DimensionSuggestionProvider.java
+++ /dev/null
@@ -1,88 +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.edit;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.attrinfo.models.Attr;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.androidide.lsp.util.StringUtils;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Handles editing dimension attributes.
- *
- * @author Akash Yadav
- */
-public class DimensionSuggestionProvider extends BaseSuggestionProvider {
-
- /** The dimension units that will be suggested. */
- private final List dimensions = new ArrayList<>();
-
- public DimensionSuggestionProvider(File layout) {
- super(layout);
-
- this.dimensions.add("dp");
- this.dimensions.add("sp");
- this.dimensions.add("px");
- this.dimensions.add("pt");
- this.dimensions.add("in");
- this.dimensions.add("mm");
- }
-
- @Override
- public boolean checkFormat(int format) {
- return (format & Attr.DIMENSION) != 0;
- }
-
- @Override
- public @NonNull List suggest(IAttribute attribute, @NonNull String prefix) {
- final var list = new ArrayList();
- if (prefix.length() > 0 && Character.isDigit(prefix.charAt(0))) {
- // Fixed dimension values
- // e.g. 10dp
-
- var val = extractDimensionVal(prefix);
- for (var unit : this.dimensions) {
- final var dimension = val + unit;
- if (StringUtils.matchesFuzzy(dimension, prefix, true)) {
- list.add(dimension);
- }
- }
- }
-
- return list;
- }
-
- private int extractDimensionVal(@NonNull String prefix) {
- StringBuilder s = new StringBuilder();
- var i = 0;
- while (i < prefix.length()) {
- if (Character.isDigit(prefix.charAt(i))) {
- s.append(prefix.charAt(i));
- } else {
- break;
- }
- i++;
- }
-
- return Integer.parseInt(s.toString());
- }
-}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/edit/IValueSuggestionProvider.java b/app/src/main/java/com/itsaky/androidide/ui/edit/IValueSuggestionProvider.java
deleted file mode 100644
index 665f47207..000000000
--- a/app/src/main/java/com/itsaky/androidide/ui/edit/IValueSuggestionProvider.java
+++ /dev/null
@@ -1,51 +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.edit;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-
-import java.util.List;
-
-/**
- * An attribute value provider provides suggestions while editing an attribute value.
- *
- * @author Akash Yadav
- */
-public interface IValueSuggestionProvider {
-
- /**
- * Check if the given format is supported by this provider.
- *
- * @param format The formats to check.
- * @return true if the given formats contain a supported format, false
- * otherwise.
- */
- boolean checkFormat(int format);
-
- /**
- * Provide suggestions for the given attribute.
- *
- * @param attribute The attribute to provide suggestions for.
- * @param prefix The prefix (partial identifier) to filter the suggestions.
- * @return The suggestion items. Must not be null.
- */
- @NonNull
- List suggest(IAttribute attribute, String prefix);
-}
diff --git a/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java b/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java
index da59527e7..7d3011451 100644
--- a/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java
+++ b/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java
@@ -24,9 +24,9 @@ import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.FLA
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.FLAG_WS_TRAILING;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.FONT_LIGATURES;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.FONT_SIZE;
+import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.USE_CUSTOM_FONT;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.USE_ICU;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.USE_MAGNIFER;
-import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.USE_CUSTOM_FONT;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.WORD_WRAP;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.getDrawEmptyLineWs;
import static com.itsaky.androidide.preferences.internal.EditorPreferencesKt.getDrawInnerWs;
@@ -70,7 +70,6 @@ import com.itsaky.androidide.utils.FileUtil;
import com.itsaky.androidide.utils.ILogger;
import com.itsaky.androidide.utils.LSPUtils;
import com.itsaky.androidide.utils.TypefaceUtilsKt;
-import com.itsaky.inflater.values.ValuesTableFactory;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -78,7 +77,6 @@ import org.greenrobot.eventbus.ThreadMode;
import java.io.File;
import java.io.IOException;
-import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import io.github.rosemoe.sora.lang.EmptyLanguage;
@@ -385,9 +383,6 @@ public class CodeEditorView extends LinearLayout {
private void notifySaved() {
binding.editor.dispatchDocumentSaveEvent();
- if (Objects.requireNonNull(getFile()).getName().endsWith(".xml")) {
- ValuesTableFactory.syncWithFile(getFile());
- }
}
public LayoutCodeEditorBinding getBinding() {
@@ -422,7 +417,7 @@ public class CodeEditorView extends LinearLayout {
LOG.warn("Editor layout is null content=" + binding + ", searchLayout=" + searchLayout);
return;
}
-
+
searchLayout.beginSearchMode();
}
diff --git a/app/src/main/res/layout/activity_designer.xml b/app/src/main/res/layout/activity_designer.xml
deleted file mode 100755
index c0dd43e52..000000000
--- a/app/src/main/res/layout/activity_designer.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build-tools/aaptcompiler/src/test/java/com/itsaky/androidide/aaptcompiler/CompilerTest.kt b/build-tools/aaptcompiler/src/test/java/com/itsaky/androidide/aaptcompiler/CompilerTest.kt
index 1b2cb34e6..e73862538 100644
--- a/build-tools/aaptcompiler/src/test/java/com/itsaky/androidide/aaptcompiler/CompilerTest.kt
+++ b/build-tools/aaptcompiler/src/test/java/com/itsaky/androidide/aaptcompiler/CompilerTest.kt
@@ -19,14 +19,17 @@ package com.itsaky.androidide.aaptcompiler
import com.android.aaptcompiler.BlameLogger
import com.android.aaptcompiler.ResourceCompilerOptions
+import com.android.aaptcompiler.ResourceFile
+import com.android.aaptcompiler.ResourceName
+import com.android.aaptcompiler.XmlProcessor
import com.android.aaptcompiler.compileResource
+import com.android.aaptcompiler.extractPathData
import com.android.utils.StdLogger
import com.android.utils.StdLogger.Level.VERBOSE
import java.nio.file.Paths
import kotlin.io.path.absolute
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
import org.robolectric.RobolectricTestRunner
/** @author Akash Yadav */
@@ -45,4 +48,19 @@ class CompilerTest {
compileResource(input, output, ResourceCompilerOptions(), BlameLogger(StdLogger(VERBOSE)))
println("Compiled in ${System.nanoTime() - start} nano seconds")
}
+
+ @Test
+ fun `test xml processor`() {
+ val input =
+ Paths.get(".", "src/test/resources/layout/activity_editor.xml").absolute().normalize().toFile()
+ val pathData = extractPathData(input, input.absolutePath)
+ val resFile = ResourceFile(
+ ResourceName("", pathData.type!!, pathData.name),
+ pathData.config,
+ pathData.source,
+ ResourceFile.Type.ProtoXml
+ )
+ val processor = XmlProcessor(pathData.source, BlameLogger(StdLogger(VERBOSE)))
+ processor.process(resFile, input.inputStream().buffered())
+ }
}
diff --git a/build-tools/aaptcompiler/src/test/resources/layout/activity_editor.xml b/build-tools/aaptcompiler/src/test/resources/layout/activity_editor.xml
new file mode 100755
index 000000000..a62fa02ea
--- /dev/null
+++ b/build-tools/aaptcompiler/src/test/resources/layout/activity_editor.xml
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java b/common/src/main/java/com/itsaky/androidide/utils/ResourceUtils.kt
similarity index 63%
rename from xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java
rename to common/src/main/java/com/itsaky/androidide/utils/ResourceUtils.kt
index 43c46148e..31b97a3e6 100644
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/DimensionResource.java
+++ b/common/src/main/java/com/itsaky/androidide/utils/ResourceUtils.kt
@@ -14,18 +14,21 @@
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see .
*/
-package com.itsaky.inflater.values.models;
-import androidx.annotation.NonNull;
+package com.itsaky.androidide.utils
-/**
- * Represents a dimension value.
- *
- * @author Akash Yadav
- */
-public class DimensionResource extends AbstractResource {
+import android.content.Context
+import android.content.res.Resources.Theme
+import android.util.TypedValue
- public DimensionResource(@NonNull String name, @NonNull String value) {
- super(name, value);
- }
+@JvmOverloads
+fun Context.resolveAttr(id: Int, resolveRefs: Boolean = true): Int {
+ return theme.resolveAttr(id)
}
+
+@JvmOverloads
+fun Theme.resolveAttr(id: Int, resolveRefs: Boolean = true): Int =
+ TypedValue().let {
+ resolveAttribute(id, it, resolveRefs)
+ it.data
+ }
diff --git a/lsp/api/build.gradle b/lsp/api/build.gradle
index 303399825..f6280e001 100644
--- a/lsp/api/build.gradle
+++ b/lsp/api/build.gradle
@@ -69,7 +69,7 @@ dependencies {
api project (':lsp:models')
api project (':preferences')
- compileOnly project (':xml-inflater')
+ compileOnly project (':sdk-info')
compileOnly project (':actions')
compileOnly project (':common')
}
diff --git a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/XMLLanguageServer.java b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/XMLLanguageServer.java
index c15f81e55..d0c12622d 100644
--- a/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/XMLLanguageServer.java
+++ b/lsp/xml/src/main/java/com/itsaky/androidide/lsp/xml/XMLLanguageServer.java
@@ -42,7 +42,6 @@ import com.itsaky.androidide.lsp.xml.providers.CodeFormatProvider;
import com.itsaky.androidide.lsp.xml.providers.XmlCompletionProvider;
import com.itsaky.androidide.models.Range;
import com.itsaky.androidide.projects.api.Project;
-import com.itsaky.sdk.SDKInfo;
import org.jetbrains.annotations.Nullable;
@@ -59,12 +58,11 @@ public class XMLLanguageServer implements ILanguageServer {
public static final String SERVER_ID = "xml";
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-
private ILanguageClient client;
+
private IServerSettings settings;
public XMLLanguageServer() {}
-
@Override
public String getServerId() {
diff --git a/sdk-info/src/main/java/com/itsaky/apiinfo/ApiInfo.java b/sdk-info/src/main/java/com/itsaky/apiinfo/ApiInfo.java
deleted file mode 100755
index 55417ca38..000000000
--- a/sdk-info/src/main/java/com/itsaky/apiinfo/ApiInfo.java
+++ /dev/null
@@ -1,186 +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.apiinfo;
-
-import android.content.res.Resources;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.apiinfo.models.ClassInfo;
-import com.itsaky.apiinfo.models.FieldInfo;
-import com.itsaky.apiinfo.models.MethodInfo;
-import com.itsaky.androidide.resources.R;
-
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.HashMap;
-import java.util.Map;
-
-public class ApiInfo {
-
- public static final String NAME = "name";
- public static final String SINCE = "since";
- public static final String DEPRECATED = "deprecated";
- public static final String REMOVED = "removed";
- public static final String EXTENDS = "extends";
- public static final String IMPLEMENTS = "implements";
- public static final String FIELD = "field";
- public static final String METHOD = "method";
- private final Map classInfos;
- private boolean read = false;
-
- public ApiInfo(@NonNull final Resources resources) throws Exception {
- this.classInfos = new HashMap<>();
- doRead(resources);
- }
-
- public void doRead(Resources resources) throws Exception {
- final InputStream in = resources.openRawResource(R.raw.versions_xml);
- if (in == null) {
- throw new Resources.NotFoundException("Cannot find versions.xml");
- }
- Document doc = Jsoup.parse(readStream(in));
- Elements classes = doc.getElementsByTag("api").first().getElementsByTag("class");
- if (classes.size() <= 0) {
- return;
- }
-
- for (Element clazz : classes) {
- ClassInfo info = parseClassInfo(clazz);
- if (info != null) classInfos.put(info.name, info);
- }
-
- read = true;
- }
-
- private String readStream(InputStream in) throws IOException {
- final StringBuilder sb = new StringBuilder();
- final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- String line;
- while ((line = reader.readLine()) != null) {
- sb.append(line.trim());
- sb.append("\n");
- }
- return sb.substring(sb.indexOf(" 0) {
- for (Element iface : interfaces) {
- info.interfaces.add(iface.attr(NAME));
- }
- }
-
- Elements fields = clazz.getElementsByTag(FIELD);
- if (fields.size() > 0) {
- for (Element field : fields) {
- putField(field, info);
- }
- }
-
- Elements methods = clazz.getElementsByTag(METHOD);
- if (methods.size() > 0) {
- for (Element method : methods) {
- putMethod(method, info);
- }
- }
-
- return info;
- }
-
- private void putField(Element field, ClassInfo clazz) {
- if (!field.hasAttr(NAME)) return;
- FieldInfo info = new FieldInfo();
-
- info.name = field.attr(NAME);
-
- if (field.hasAttr(SINCE)) {
- info.since = Integer.parseInt(field.attr(SINCE));
- }
-
- if (field.hasAttr(DEPRECATED)) {
- info.deprecated = Integer.parseInt(field.attr(DEPRECATED));
- }
-
- if (field.hasAttr(REMOVED)) {
- info.removed = Integer.parseInt(field.attr(REMOVED));
- }
-
- clazz.fields.put(info.name, info);
- }
-
- private void putMethod(Element method, ClassInfo clazz) {
- if (!method.hasAttr(NAME)) return;
- MethodInfo info = new MethodInfo();
-
- info.name = method.attr(NAME);
- info.simpleName = info.name.substring(0, info.name.indexOf("("));
-
- if (method.hasAttr(SINCE)) {
- info.since = Integer.parseInt(method.attr(SINCE));
- }
-
- if (method.hasAttr(DEPRECATED)) {
- info.deprecated = Integer.parseInt(method.attr(DEPRECATED));
- }
-
- if (method.hasAttr(REMOVED)) {
- info.removed = Integer.parseInt(method.attr(REMOVED));
- }
-
- clazz.methods.put(info.name, info);
- }
-
- public boolean hasRead() {
- return read;
- }
-
- public ClassInfo getClassByName(String qualifiedName) {
- return classInfos.get(qualifiedName);
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/apiinfo/models/ClassInfo.java b/sdk-info/src/main/java/com/itsaky/apiinfo/models/ClassInfo.java
deleted file mode 100755
index a5d2370d5..000000000
--- a/sdk-info/src/main/java/com/itsaky/apiinfo/models/ClassInfo.java
+++ /dev/null
@@ -1,88 +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.apiinfo.models;
-
-import android.text.TextUtils;
-
-import org.eclipse.jdt.core.Signature;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Holds information about a class */
-public class ClassInfo extends Info {
-
- /** Interfaces that this class implements */
- public final List interfaces = new ArrayList<>();
- /** Fields of this class */
- public final Map fields = new HashMap<>();
- /** Methods of this class */
- public final Map methods = new HashMap<>();
- /** Superclass of this class */
- public String superClass;
-
- /**
- * Get the field by its simple name
- *
- * @param name Name of the field to find
- */
- public FieldInfo getFieldByName(String name) {
- return fields.get(name);
- }
-
- /**
- * Get method by its name and parameter types
- *
- * @param name Name of the method to find
- * @param parameters Parameter types of the method
- */
- public MethodInfo getMethod(String name, String[] parameters) {
-
- // Convert parameter types to their binary version
- final String[] parameterTypes = new String[parameters.length];
- for (int i = 0; i < parameters.length; i++) {
- String paramType = parameters[i];
- String binaryParamType = Signature.createTypeSignature(paramType, true /* isResolved */);
- parameterTypes[i] = binaryParamType;
- }
-
- for (Map.Entry entry : methods.entrySet()) {
- MethodInfo method = entry.getValue();
-
- // Check if this method's simple name is what we are looking for
- if (method != null && method.simpleName.trim().equals(name.trim())) {
-
- // Get parameter types of this method
- // Takes binary representation, returns binary representation
- String[] paramTypes = Signature.getParameterTypes(method.name);
-
- // Join the parameters to check if they are equal This is just more efficient
- final String params1 = TextUtils.join(",", paramTypes);
- final String params2 = TextUtils.join(",", parameterTypes);
-
- // We found what we were looking for!
- if (params1.equals(params2)) return method;
- }
- }
- return null;
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/apiinfo/models/FieldInfo.java b/sdk-info/src/main/java/com/itsaky/apiinfo/models/FieldInfo.java
deleted file mode 100755
index 650e98416..000000000
--- a/sdk-info/src/main/java/com/itsaky/apiinfo/models/FieldInfo.java
+++ /dev/null
@@ -1,27 +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.apiinfo.models;
-
-/**
- * Holds information about a field
- *
- * No difference as compared to Info
- */
-public class FieldInfo extends Info {}
diff --git a/sdk-info/src/main/java/com/itsaky/apiinfo/models/Info.java b/sdk-info/src/main/java/com/itsaky/apiinfo/models/Info.java
deleted file mode 100755
index bb1e89e9a..000000000
--- a/sdk-info/src/main/java/com/itsaky/apiinfo/models/Info.java
+++ /dev/null
@@ -1,36 +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.apiinfo.models;
-
-/** Base class for information about a class, method, field */
-public abstract class Info {
-
- /** Name of this class, method or field */
- public String name = "";
-
- /** API level in which this info was deprecated */
- public int deprecated = -1;
-
- /** API level in which this was added */
- public int since = -1;
-
- /** API level in which this was removed */
- public int removed = -1;
-}
diff --git a/sdk-info/src/main/java/com/itsaky/apiinfo/models/MethodInfo.java b/sdk-info/src/main/java/com/itsaky/apiinfo/models/MethodInfo.java
deleted file mode 100755
index 68a2d4508..000000000
--- a/sdk-info/src/main/java/com/itsaky/apiinfo/models/MethodInfo.java
+++ /dev/null
@@ -1,35 +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.apiinfo.models;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Holds information about a method */
-public class MethodInfo extends Info {
-
- /** Parameter types of this method */
- public final List parameters = new ArrayList<>();
- /**
- * In case of a method, the {@link com.itsaky.apiinfo.models.Info#name} contains signature of the
- * method This field contains the actual simple name
- */
- public String simpleName;
-}
diff --git a/sdk-info/src/main/java/com/itsaky/attrinfo/AttrInfo.java b/sdk-info/src/main/java/com/itsaky/attrinfo/AttrInfo.java
deleted file mode 100755
index c2cd2a059..000000000
--- a/sdk-info/src/main/java/com/itsaky/attrinfo/AttrInfo.java
+++ /dev/null
@@ -1,229 +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.attrinfo;
-
-import android.content.res.Resources;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.attrinfo.models.Attr;
-import com.itsaky.attrinfo.models.Styleable;
-import com.itsaky.androidide.resources.R;
-import com.itsaky.xml.INamespace;
-
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Parser;
-
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.TreeMap;
-
-/**
- * A parser for parsing attrs.xml. This parser maps the attributes with the declared
- * styleables.
- *
- * @author Akash Yadav
- */
-public class AttrInfo {
-
- /** Styles mapped by names; */
- public final Map styles = new HashMap<>();
-
- public final Map attributes = new TreeMap<>();
- public final Styleable NO_PARENT;
-
- public AttrInfo(@NonNull final Resources resources) throws Exception {
- NO_PARENT = new Styleable("");
-
- Objects.requireNonNull(resources, "Cannot read from null resources.");
-
- final var in = resources.openRawResource(R.raw.attrs_xml);
- parseFromStream(in);
- }
-
- @Nullable
- public Attr getAttribute(@NonNull final String name) {
- var attr = this.attributes.get(name);
- if (attr == null) {
- final var a = NO_PARENT.attributes.stream().filter(aa -> aa.name.equals(name)).findFirst();
- attr = a.orElse(null);
- }
-
- return attr;
- }
-
- @NonNull
- public Map getAttributes() {
- return this.attributes;
- }
-
- @Nullable
- public Styleable getStyle(@NonNull final String name) {
- return this.styles.get(name);
- }
-
- @NonNull
- public Map getStyles() {
- return styles;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(NO_PARENT, styles);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof AttrInfo)) {
- return false;
- }
- AttrInfo that = (AttrInfo) o;
- return Objects.equals(NO_PARENT, that.NO_PARENT) && Objects.equals(styles, that.styles);
- }
-
- @NonNull
- @Override
- public String toString() {
- return "AttrInfoCompat{" + "NO_PARENT=" + NO_PARENT + ", styles=" + styles + '}';
- }
-
- protected void parseFromStream(InputStream in) throws Exception {
- Objects.requireNonNull(in, "Cannot read from null input stream");
-
- Document doc = Jsoup.parse(in, null, "", Parser.xmlParser());
- final var resources = doc.getElementsByTag("resources").first();
-
- parseFromResources(resources);
- }
-
- protected void parseFromResources(Element resources) {
- Objects.requireNonNull(resources, "Cannot parse from null resource element");
-
- this.styles.clear();
-
- for (int i = 0; i < resources.childrenSize(); i++) {
- final var child = resources.child(i);
- if (child.tagName().equals("declare-styleable")) {
- this.styles.put(parseStyleable(child).name, parseStyleable(child));
- } else if (child.tagName().equals("attr")) {
- NO_PARENT.attributes.add(parseAttr(child));
- }
- }
-
- this.styles.put(NO_PARENT.name, NO_PARENT);
- }
-
- @NonNull
- protected Styleable parseStyleable(@NonNull final Element styleable) {
- checkName(styleable);
-
- final var name = styleable.attr("name");
- final var style = new Styleable(name);
-
- for (int i = 0; i < styleable.childrenSize(); i++) {
- final var attr = styleable.child(i);
- if (!attr.tagName().equals("attr")) {
- continue;
- }
-
- style.attributes.add(parseAttr(attr));
- }
-
- return style;
- }
-
- @NonNull
- protected Attr parseAttr(@NonNull final Element attr) {
- checkName(attr);
-
- final var attribute = new Attr(attr.attr("name"));
- if (attribute.name.contains(":")) {
- final var split = attribute.name.split(":", 2);
- attribute.namespace = INamespace.ANDROID;
- attribute.name = split[1];
- }
-
- if (attribute.name.equals("gravity")) {
- System.out.println("This is it");
- }
-
- if (attr.hasAttr("format")) {
- attribute.format = Attr.formatForName(attr.attr("format"));
- if (attribute.hasFormat(Attr.BOOLEAN)) {
- attribute.possibleValues.add("true");
- attribute.possibleValues.add("false");
- }
- }
-
- final var enums = attr.getElementsByTag("enum");
- final var flags = attr.getElementsByTag("flag");
-
- if (enums.size() > 0) {
- for (var enumEntry : enums) {
- checkName(enumEntry);
- attribute.possibleValues.add(enumEntry.attr("name"));
- }
-
- if (!attribute.hasFormat(Attr.ENUM)) {
- attribute.format |= Attr.ENUM;
- }
- }
-
- if (flags.size() > 0) {
- for (var flagEntry : flags) {
- checkName(flagEntry);
- attribute.possibleValues.add(flagEntry.attr("name"));
- }
-
- if (!attribute.hasFormat(Attr.FLAG)) {
- attribute.format |= Attr.FLAG;
- }
- }
-
- if (this.attributes.containsKey(attribute.name)) {
- final var present = this.attributes.get(attribute.name);
- if (present != null) {
- if (present.hasPossibleValues()) {
- attribute.possibleValues.addAll(present.possibleValues);
- }
-
- if (attribute.format == 0 && present.format != 0) {
- attribute.format = present.format;
- }
- }
- }
-
- this.attributes.put(attribute.name, attribute);
-
- return attribute;
- }
-
- private void checkName(@NonNull Element child) {
- if (!child.hasAttr("name")) {
- throw new IllegalStateException("Element does not have 'name' attribute: " + child);
- }
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/attrinfo/models/Attr.java b/sdk-info/src/main/java/com/itsaky/attrinfo/models/Attr.java
deleted file mode 100755
index 88359c963..000000000
--- a/sdk-info/src/main/java/com/itsaky/attrinfo/models/Attr.java
+++ /dev/null
@@ -1,255 +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.attrinfo.models;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.xml.INamespace;
-
-import org.jetbrains.annotations.Contract;
-
-import java.util.ArrayList;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.regex.Pattern;
-
-/**
- * Represents an xml attribute which is read from {@code attrs.xml}.
- *
- * @author Akash Yadav
- * @see com.itsaky.attrinfo.AttrInfo
- */
-public class Attr implements Parcelable {
-
- public static final int REFERENCE = 1;
- public static final int COLOR = 1 << 1;
- public static final int BOOLEAN = 1 << 2;
- public static final int DIMENSION = 1 << 3;
- public static final int FLOAT = 1 << 4;
- public static final int INTEGER = 1 << 5;
- public static final int FRACTION = 1 << 6;
- public static final int STRING = 1 << 7;
- public static final int ENUM = 1 << 8;
- public static final int FLAG = 1 << 9;
- public static final int UNKNOWN = 1 << 10;
-
- public static final String FORMAT_REFERENCE = "reference";
- public static final String FORMAT_COLOR = "color";
- public static final String FORMAT_BOOLEAN = "boolean";
- public static final String FORMAT_DIMENSION = "dimension";
- public static final String FORMAT_FLOAT = "float";
- public static final String FORMAT_INTEGER = "integer";
- public static final String FORMAT_FRACTION = "fraction";
- public static final String FORMAT_STRING = "string";
- public static final String FORMAT_ENUM = "enum";
- public static final String FORMAT_FLAG = "flag";
- public static final Creator CREATOR =
- new Creator<>() {
- @Override
- public Attr createFromParcel(Parcel in) {
- return new Attr(in);
- }
-
- @Override
- public Attr[] newArray(int size) {
- return new Attr[size];
- }
- };
- private static final ILogger LOG = ILogger.newInstance("AttrInfo::Attr");
- public INamespace namespace;
- public String name;
- public Set possibleValues;
- public int format;
-
- public Attr(String name) {
- this(name, INamespace.ANDROID);
- }
-
- public Attr(String name, INamespace namespace) {
- this.name = name;
- this.namespace = namespace;
- this.possibleValues = new TreeSet<>();
- }
-
- protected Attr(@NonNull Parcel in) {
- this.namespace = in.readParcelable(INamespace.class.getClassLoader());
- this.name = in.readString();
- this.format = in.readInt();
-
- final var list = new ArrayList();
- in.readStringList(list);
- this.possibleValues = new TreeSet<>(list);
- }
-
- public static int formatForName(@NonNull String names) {
- var result = 0;
- if (names.contains("|")) {
- for (var name : names.split(Pattern.quote("|"))) {
- result |= formatForSingleName(name);
- }
- } else {
- result = formatForSingleName(names);
- }
- return result;
- }
-
- @Contract(pure = true)
- public static int formatForSingleName(@NonNull String name) {
- switch (name) {
- case FORMAT_REFERENCE:
- return REFERENCE;
- case FORMAT_COLOR:
- return COLOR;
- case FORMAT_BOOLEAN:
- return BOOLEAN;
- case FORMAT_DIMENSION:
- return DIMENSION;
- case FORMAT_FLOAT:
- return FLOAT;
- case FORMAT_INTEGER:
- return INTEGER;
- case FORMAT_FRACTION:
- return FRACTION;
- case FORMAT_STRING:
- return STRING;
- case FORMAT_ENUM:
- return ENUM;
- case FORMAT_FLAG:
- return FLAG;
- }
-
- return UNKNOWN;
- }
-
- public static String createFormatText(int format) {
- final var formats = new ArrayList();
- if ((format & REFERENCE) != 0) {
- formats.add(FORMAT_REFERENCE);
- }
-
- if ((format & COLOR) != 0) {
- formats.add(FORMAT_COLOR);
- }
-
- if ((format & BOOLEAN) != 0) {
- formats.add(FORMAT_BOOLEAN);
- }
-
- if ((format & DIMENSION) != 0) {
- formats.add(FORMAT_DIMENSION);
- }
-
- if ((format & FLOAT) != 0) {
- formats.add(FORMAT_FLOAT);
- }
-
- if ((format & INTEGER) != 0) {
- formats.add(FORMAT_INTEGER);
- }
-
- if ((format & FRACTION) != 0) {
- formats.add(FORMAT_FRACTION);
- }
-
- if ((format & STRING) != 0) {
- formats.add(FORMAT_STRING);
- }
-
- if ((format & ENUM) != 0) {
- formats.add(FORMAT_ENUM);
- }
-
- if ((format & FLAG) != 0) {
- formats.add(FORMAT_FLAG);
- }
-
- if (formats.isEmpty()) {
- formats.add("unknown");
- }
-
- return TextUtils.join("|", formats);
- }
-
- public boolean hasPossibleValues() {
- return possibleValues != null && possibleValues.size() > 0;
- }
-
- public boolean hasFormat(int format) {
- return (this.format & format) != 0;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(namespace, name, possibleValues, format);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- Attr attr = (Attr) o;
- return format == attr.format
- && Objects.equals(namespace, attr.namespace)
- && Objects.equals(name, attr.name)
- && Objects.equals(possibleValues, attr.possibleValues);
- }
-
- @NonNull
- @Override
- public String toString() {
- return "Attr ["
- + " name: "
- + name
- + "\n"
- + " namespace: "
- + namespace
- + "\n"
- + " values: "
- + TextUtils.join(", ", this.possibleValues)
- + "\n"
- + " format: "
- + format
- + "\n"
- + "]";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(namespace, flags);
- dest.writeString(name);
- dest.writeInt(format);
- dest.writeStringList(new ArrayList<>(this.possibleValues));
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/attrinfo/models/Styleable.java b/sdk-info/src/main/java/com/itsaky/attrinfo/models/Styleable.java
deleted file mode 100644
index ebe1063eb..000000000
--- a/sdk-info/src/main/java/com/itsaky/attrinfo/models/Styleable.java
+++ /dev/null
@@ -1,66 +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.attrinfo.models;
-
-import androidx.annotation.NonNull;
-
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * A <declare-styleable>.
- *
- * @author Akash Yadav
- */
-public class Styleable {
-
- public final String name;
- public final Set attributes = new HashSet<>();
-
- public Styleable(String name) {
- if (name == null || name.trim().length() <= 0) {
- throw new IllegalArgumentException("Invalid name specified for declared styleable");
- }
-
- this.name = name.trim();
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(name, attributes);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof Styleable)) {
- return false;
- }
- Styleable styleable = (Styleable) o;
- return Objects.equals(name, styleable.name) && Objects.equals(attributes, styleable.attributes);
- }
-
- @NonNull
- @Override
- public String toString() {
- return "Styleable{" + "name='" + name + '\'' + ", attributes=" + attributes + '}';
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/sdk/SDKInfo.java b/sdk-info/src/main/java/com/itsaky/sdk/SDKInfo.java
deleted file mode 100644
index 252e0c6ff..000000000
--- a/sdk-info/src/main/java/com/itsaky/sdk/SDKInfo.java
+++ /dev/null
@@ -1,67 +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.sdk;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.apiinfo.ApiInfo;
-import com.itsaky.attrinfo.AttrInfo;
-import com.itsaky.widgets.WidgetInfo;
-
-import java.util.Objects;
-
-/**
- * Class that holds all of the 'sdk-info' APIs.
- *
- * @see ApiInfo
- * @see AttrInfo
- * @see WidgetInfo
- * @author Akash Yadav
- */
-public class SDKInfo {
-
- private final AttrInfo attrInfo;
- private final ApiInfo apiInfo;
- private final WidgetInfo widgetInfo;
-
- public SDKInfo(@NonNull final Context context) throws Exception {
- this(context.getResources());
- }
-
- public SDKInfo(@NonNull final Resources resources) throws Exception {
- Objects.requireNonNull(resources);
- this.apiInfo = new ApiInfo(resources);
- this.attrInfo = new AttrInfo(resources);
- this.widgetInfo = new WidgetInfo(resources);
- }
-
- public AttrInfo getAttrInfo() {
- return attrInfo;
- }
-
- public ApiInfo getApiInfo() {
- return apiInfo;
- }
-
- public WidgetInfo getWidgetInfo() {
- return widgetInfo;
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/widgets/WidgetInfo.java b/sdk-info/src/main/java/com/itsaky/widgets/WidgetInfo.java
deleted file mode 100755
index 3cce0cbfd..000000000
--- a/sdk-info/src/main/java/com/itsaky/widgets/WidgetInfo.java
+++ /dev/null
@@ -1,103 +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.widgets;
-
-import android.content.res.Resources;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.widgets.models.Widget;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Collection;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-public class WidgetInfo {
-
- private final SortedMap widgets;
- private final SortedMap params;
-
- public WidgetInfo(@NonNull final Resources resources) throws IOException {
- this.widgets = new TreeMap<>();
- this.params = new TreeMap<>();
- readWidgets(resources);
- }
-
- private void readWidgets(@NonNull final Resources resources) throws IOException {
- final InputStream in = resources.openRawResource(com.itsaky.androidide.resources.R.raw.widgets);
- if (in == null) {
- return;
- }
-
- final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- String line;
- while ((line = reader.readLine()) != null) {
- final var split = line.split("\\s");
- final var name = split[0];
- if (name == null || name.trim().isEmpty()) {
- continue;
- }
-
- final var code = name.charAt(0);
-
- final var entryName = name.substring(1);
- final var isLayout = code == 'L'; // L -> Layout, W -> Widget, P -> LayoutParam
- final var superclasses = new String[split.length - 1];
-
- System.arraycopy(split, 1, superclasses, 0, superclasses.length);
-
- if (code == 'P') {
- final var className = entryName.substring(0, entryName.lastIndexOf("."));
- this.params.put(className, superclasses);
- } else {
- final var widget = new Widget(entryName, isLayout);
- widget.superclasses = superclasses;
- widgets.put(entryName, widget);
- }
- }
- }
-
- public Widget getWidget(String name) {
- return this.widgets.getOrDefault(name, null);
- }
-
- @Nullable
- public Widget getWidgetBySimpleName(@NonNull final String name) {
- for (final var entry : this.widgets.entrySet()) {
- final var key = entry.getKey();
- final var simple = key.substring(key.lastIndexOf(".") + 1);
- if (simple.equals(name)) {
- return entry.getValue();
- }
- }
- return null;
- }
-
- public Collection getWidgets() {
- return this.widgets.values();
- }
-
- public String[] getLayoutParamSuperClasses(final String className) {
- return this.params.get(className);
- }
-}
diff --git a/sdk-info/src/main/java/com/itsaky/widgets/models/Widget.java b/sdk-info/src/main/java/com/itsaky/widgets/models/Widget.java
deleted file mode 100755
index 075cec0b2..000000000
--- a/sdk-info/src/main/java/com/itsaky/widgets/models/Widget.java
+++ /dev/null
@@ -1,46 +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.widgets.models;
-
-import androidx.annotation.NonNull;
-
-public class Widget implements Comparable {
-
- public String name;
- public String simpleName;
- public boolean isViewGroup;
-
- public String[] superclasses = new String[0];
-
- public Widget(@NonNull String name, boolean isViewGroup) {
- this.name = name;
- this.simpleName = name.substring(name.lastIndexOf(".") + 1);
- this.isViewGroup = isViewGroup;
- }
-
- @Override
- public int compareTo(Widget that) {
- if (that != null) {
- return this.simpleName.compareTo(that.simpleName);
- }
-
- return -1;
- }
-}
diff --git a/settings.gradle b/settings.gradle
index 6ff5dc06e..de5204aef 100755
--- a/settings.gradle
+++ b/settings.gradle
@@ -12,7 +12,6 @@ include ':lookup'
include ':sdk-info'
include ':shared'
include ':treeview'
-include ':xml-inflater'
include ':gradle-plugin'
diff --git a/tests/test-home/.androidide/init/model.jar b/tests/test-home/.androidide/init/model.jar
index 235ecfe3b..6387e73c5 100644
Binary files a/tests/test-home/.androidide/init/model.jar and b/tests/test-home/.androidide/init/model.jar differ
diff --git a/xml-inflater/.gitignore b/xml-inflater/.gitignore
deleted file mode 100644
index bb0d480e4..000000000
--- a/xml-inflater/.gitignore
+++ /dev/null
@@ -1,85 +0,0 @@
-# Built application files
-*.apk
-*.aar
-*.ap_
-*.aab
-
-# Files for the ART/Dalvik VM
-*.dex
-
-# Java class files
-*.class
-
-# Generated files
-/bin/
-/gen/
-/out/
-# Uncomment the following line in case you need and you don't have the release build type files in your app
-# release/
-
-# Gradle files
-.gradle/
-/build/
-
-# Local configuration file (sdk path, etc)
-local.properties
-
-# Proguard folder generated by Eclipse
-proguard/
-
-# Log Files
-*.log
-
-# Android Studio Navigation editor temp files
-.navigation/
-
-# Android Studio captures folder
-captures/
-
-# IntelliJ
-*.iml
-.idea/workspace.xml
-.idea/tasks.xml
-.idea/gradle.xml
-.idea/assetWizardSettings.xml
-.idea/dictionaries
-.idea/libraries
-# Android Studio 3 in .gitignore file.
-.idea/caches
-.idea/modules.xml
-# Comment next line if keeping position of elements in Navigation Editor is relevant for you
-.idea/navEditor.xml
-
-# Keystore files
-# Uncomment the following lines if you do not want to check your keystore files in.
-#*.jks
-#*.keystore
-
-# External native build folder generated in Android Studio 2.2 and later
-.externalNativeBuild
-.cxx/
-
-# Google Services (e.g. APIs or Firebase)
-# google-services.json
-
-# Freeline
-freeline.py
-freeline/
-freeline_project_description.json
-
-# fastlane
-fastlane/report.xml
-fastlane/Preview.html
-fastlane/screenshots
-fastlane/test_output
-fastlane/readme.md
-
-# Version control
-vcs.xml
-
-# lint
-lint/intermediates/
-lint/generated/
-lint/outputs/
-lint/tmp/
-# lint/reports/
diff --git a/xml-inflater/build.gradle b/xml-inflater/build.gradle
deleted file mode 100644
index 4d2c21612..000000000
--- a/xml-inflater/build.gradle
+++ /dev/null
@@ -1,44 +0,0 @@
-apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android'
-
-android {
- namespace "com.itsaky.inflater"
- compileSdkVersion rootProject.ext.compileSdk
- buildToolsVersion rootProject.ext.buildTools
-
- defaultConfig {
- minSdkVersion rootProject.ext.minSdk
- targetSdkVersion rootProject.ext.targetSdk
- }
-
- compileOptions {
- sourceCompatibility rootProject.ext.javaSourceVersion
- targetCompatibility rootProject.ext.javaTargetVersion
- }
-
- kotlinOptions {
- jvmTarget = "11"
- }
-
- buildTypes {
- release {
- minifyEnabled true
- }
- }
-}
-
-dependencies {
- implementation fileTree (dir: 'libs', include: ['*.jar'])
- implementation androidx.ktx
- implementation androidx.annotation
- implementation androidx.appcompat
-
- implementation google.guava
- implementation common.utilcode
- implementation common.jsoup
- implementation common.kotlin
-
- implementation project (":common")
- implementation project (":resources")
- api project (':sdk-info')
-}
\ No newline at end of file
diff --git a/xml-inflater/proguard-rules.pro b/xml-inflater/proguard-rules.pro
deleted file mode 100644
index 0448f7080..000000000
--- a/xml-inflater/proguard-rules.pro
+++ /dev/null
@@ -1,17 +0,0 @@
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in /Users/bogdan/Library/Android/sdk/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the proguardFiles
-# directive in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# 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 *;
-#}
diff --git a/xml-inflater/src/main/AndroidManifest.xml b/xml-inflater/src/main/AndroidManifest.xml
deleted file mode 100644
index 9c5d2fe0b..000000000
--- a/xml-inflater/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/AttrType.java b/xml-inflater/src/main/java/com/itsaky/inflater/AttrType.java
deleted file mode 100644
index f93b9b1f5..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/AttrType.java
+++ /dev/null
@@ -1,117 +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.inflater;
-
-/**
- * Value type of {@link IAttribute}
- *
- * @author Akash Yadav
- */
-public enum AttrType {
-
- /** Refers to another resource */
- REFERENCE("reference"),
-
- /** Color value */
- COLOR("color"),
-
- /** Either {@code true} or {@code false} */
- BOOLEAN("boolean"),
-
- /** A dimension like 10dp, 14sp etc. */
- DIMENSION("dimension"),
-
- /** A floating point number. E.g.: 1.9, 123.45 */
- FLOAT("float"),
-
- /** An integer value */
- INTEGER("integer"),
-
- /** A string value */
- STRING("string"),
-
- /** A fraction */
- FRACTION("fraction"),
-
- /** A enum value. Unlike {@link #FLAG}, an attribute can have only one of this. */
- ENUM("enum"),
-
- /** A flag value. May contain on or more values */
- FLAG("flag"),
-
- /** An unknown value. The layout inflater does not consider this */
- UNKNOWN("");
-
- public static final String FORMAT_REF = REFERENCE.getFormat();
- public static final String FORMAT_COLOR = COLOR.getFormat();
- public static final String FORMAT_BOOL = BOOLEAN.getFormat();
- public static final String FORMAT_DIMEN = DIMENSION.getFormat();
- public static final String FORMAT_FLOAT = FLOAT.getFormat();
- public static final String FORMAT_INT = INTEGER.getFormat();
- public static final String FORMAT_STRING = STRING.getFormat();
- public static final String FORMAT_FRACTION = FRACTION.getFormat();
- public static final String FORMAT_ENUM = ENUM.getFormat();
- public static final String FORMAT_FLAG = FLAG.getFormat();
- private final String format;
-
- private AttrType(String format) {
- this.format = format;
- }
-
- /**
- * Get the attribute type from format
- *
- * @param format Format, as declared in styleables.
- * @return The Attribute type
- */
- public static AttrType fromFormat(String format) {
- if (FORMAT_REF.equals(format)) {
- return AttrType.REFERENCE;
- } else if (FORMAT_COLOR.equals(format)) {
- return AttrType.COLOR;
- } else if (FORMAT_BOOL.equals(format)) {
- return AttrType.BOOLEAN;
- } else if (FORMAT_DIMEN.equals(format)) {
- return AttrType.DIMENSION;
- } else if (FORMAT_FLOAT.equals(format)) {
- return AttrType.FLOAT;
- } else if (FORMAT_INT.equals(format)) {
- return AttrType.INTEGER;
- } else if (FORMAT_STRING.equals(format)) {
- return AttrType.STRING;
- } else if (FORMAT_FRACTION.equals(format)) {
- return AttrType.FRACTION;
- } else if (FORMAT_ENUM.equals(format)) {
- return AttrType.ENUM;
- } else if (FORMAT_FLAG.equals(format)) {
- return AttrType.FLAG;
- }
-
- return AttrType.UNKNOWN;
- }
-
- public String getFormat() {
- return this.format;
- }
-
- public boolean hasFixedValues() {
- return this == AttrType.ENUM || this == AttrType.FLAG;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/BaseLayoutInflater.java b/xml-inflater/src/main/java/com/itsaky/inflater/BaseLayoutInflater.java
deleted file mode 100644
index a89beb16f..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/BaseLayoutInflater.java
+++ /dev/null
@@ -1,73 +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.inflater;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public abstract class BaseLayoutInflater extends ILayoutInflater {
-
- private final Set inflateListeners = new HashSet<>();
- protected boolean notify = true;
-
- @Override
- public void registerInflateListener(IInflateListener listener) {
- inflateListeners.add(listener);
- }
-
- @Override
- public void unregisterListener(IInflateListener listener) {
- inflateListeners.remove(listener);
- }
-
- protected void preInflate() {
- if (notify) {
- for (IInflateListener listener : inflateListeners) {
- listener.onBeginInflate();
- }
- }
- }
-
- protected void postApplyAttribute(IAttribute attr, IView view) {
- if (notify) {
- for (IInflateListener listener : inflateListeners) {
- listener.onApplyAttribute(attr, view);
- }
- }
- }
-
- protected void postCreateView(IView view) {
- if (notify) {
- for (IInflateListener listener : inflateListeners) {
- listener.onInflateView(view, view.getParent());
- }
- }
- }
-
- protected void postInflate(IView root) {
- if (notify) {
- for (IInflateListener listener : inflateListeners) {
- listener.onFinishInflate(root);
- }
- }
- }
-
- protected Set getInflateListeners() {
- return this.inflateListeners;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IAttribute.java b/xml-inflater/src/main/java/com/itsaky/inflater/IAttribute.java
deleted file mode 100644
index a2c6fc93f..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IAttribute.java
+++ /dev/null
@@ -1,110 +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.inflater;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.xml.INamespace;
-
-import java.util.Comparator;
-
-/**
- * Attribute that can be applied to a {@link IView}
- *
- * @author Akash Yadav
- */
-public interface IAttribute {
-
- /**
- * Returned by {@link #compareNull(Object, Object)} to indicate that the comparison must be done
- * further.
- */
- int DO_COMPARE = 2;
-
- Comparator COMPARATOR =
- (first, second) -> {
- var result = compareNull(first, second);
- if (result != IAttribute.DO_COMPARE) {
- return result;
- }
-
- result = compareNull(first.getNamespace(), second.getNamespace());
- if (result != IAttribute.DO_COMPARE) {
- return result;
- }
-
- // If we reach here, then it means that the attributes and their namespaces are not
- // null
- // First, the attributes must be compared by their namespaces
-
- final var firstNs = first.getNamespace();
- final var secondNs = second.getNamespace();
-
- if (firstNs != null && firstNs.equals(secondNs)) {
- // Compare by attribute names if the namespaces are same
- return first.getAttributeName().compareTo(second.getAttributeName());
- }
-
- // xmlns declarations must be on top
- if (firstNs != null && firstNs.equals(INamespace.DECLARATOR)) {
- return -1;
- }
-
- if (secondNs != null && secondNs.equals(INamespace.DECLARATOR)) {
- return 1;
- }
-
- return 0;
- };
-
- private static int compareNull(Object first, Object second) {
- if (first == null && second == null) {
- return 0;
- }
-
- if (first != null && second == null) {
- return -1;
- }
-
- if (first == null) {
- return 1;
- }
-
- return DO_COMPARE;
- }
-
- @Nullable
- INamespace getNamespace();
-
- @NonNull
- String getAttributeName();
-
- @NonNull
- String getValue();
-
- /**
- * Set the given string as a value to this attribute. This will set {@link #isApplied()} to return
- * {@code true}.
- *
- * @param value The value to set.
- */
- void apply(String value);
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IAttributeAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/IAttributeAdapter.java
deleted file mode 100644
index a4f41f655..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IAttributeAdapter.java
+++ /dev/null
@@ -1,52 +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.inflater;
-
-import android.view.View;
-
-/** An adapter that handles attributes of a specific type of view */
-public interface IAttributeAdapter {
-
- /**
- * Set the resource finder used by this class.
- *
- * @param resourceFinder The resource finder.
- */
- void setResourceFinder(IResourceTable resourceFinder);
-
- /**
- * Can this adapter handle attributes of the provided view?
- *
- * @param view The view to which the attributes will be applied
- * @return {@code true} if this adapter can handle attributes of the specified view
- */
- boolean isApplicableTo(View view);
-
- /**
- * Apply the provided attribute to the view.
- *
- * This will be called if and only if {@link #isApplicableTo(View)} returns {@code true}.
- *
- * @param attribute The attribute to apply
- * @param view The view to apply attribute to
- * @return {@code true} if the attribute was applied successfully {@code false} otherwise.
- */
- boolean apply(IAttribute attribute, View view);
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IDTable.java b/xml-inflater/src/main/java/com/itsaky/inflater/IDTable.java
deleted file mode 100644
index e06692f5b..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IDTable.java
+++ /dev/null
@@ -1,84 +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.inflater;
-
-import android.view.View;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Holds references to view IDs. The {@link #newRound()} must be called before inflating a layout
- * from the XML. This will make sure that we cleanup the existing IDs.
- *
- * @author Akash Yadav
- */
-public class IDTable {
-
- /**
- * Map containing the IDs. Entries are mapped by the name of the ID.
- *
- * For example : if android:id="@+id/my_id" is provided for view, then an entry will be created
- * in this map with the key : 'my_id' and a random integer as the value.
- *
- *
No entries are created for views which do not have the android:id attribute.
- */
- private static final Map ids = new HashMap<>();
-
- /** Clears the existing ID map. */
- public static void newRound() {
- ids.clear();
- }
-
- /**
- * Creates a new ID entry for the given name.
- *
- * @param idName The name of the ID.
- * @return The assigned ID.
- */
- public static int newId(String idName) {
-
- {
- // In some cases, @+id might be used as a reference
- // to another ID. So we check if an ID with the same
- // name is already present or not.
- final int id = getId(idName);
- if (id != View.NO_ID) {
- return id;
- }
- }
-
- final int id = View.generateViewId();
- ids.put(idName, id);
- return id;
- }
-
- /**
- * Get the ID mapped by the given name.
- *
- * @param name The name of the ID.
- * @return The mapped ID or {@link android.view.View#NO_ID}
- */
- public static int getId(String name) {
- final Integer id = ids.getOrDefault(name, null);
- if (id == null) {
- return View.NO_ID;
- }
- return id;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IFixedValue.java b/xml-inflater/src/main/java/com/itsaky/inflater/IFixedValue.java
deleted file mode 100644
index 660cce54b..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IFixedValue.java
+++ /dev/null
@@ -1,49 +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.inflater;
-
-/**
- * A fixed value which represents an enum of a flag
- *
- * @author Akash Yadav
- */
-public interface IFixedValue {
-
- /**
- * Is this value a flag? An attribute which accepts a flag may be combined with other flags.
- *
- * @return {@code true} if this value is a flag. {@code false} otherwise.
- */
- boolean isFlag();
-
- /**
- * The name of this enum/flag as represented in an XML file
- *
- * @return The name of this flag
- */
- String getName();
-
- /**
- * Get the value of this enum/flag. This value is fixed and should not change.
- *
- * @return Value of this enum/flag.
- */
- int getValue();
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IInflateListener.java b/xml-inflater/src/main/java/com/itsaky/inflater/IInflateListener.java
deleted file mode 100644
index 8a66b7856..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IInflateListener.java
+++ /dev/null
@@ -1,52 +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.inflater;
-
-/**
- * A listener which is invoked to notify about events in {@link ILayoutInflater}
- *
- * @author Akash Yadav
- */
-public interface IInflateListener {
-
- /** Called when the inflation process is about to start */
- void onBeginInflate();
-
- /**
- * Called when a view has been inflated
- *
- * @param view The view that will be inflated
- * @param parent The parent of this view
- */
- void onInflateView(IView view, IViewGroup parent);
-
- /**
- * Called when the attribute has been applied to the specified view
- *
- * @param attr The applied attribute
- * @param view The view to which attribute was applied
- */
- void onApplyAttribute(IAttribute attr, IView view);
-
- /**
- * Called when the inflation process finished successfully
- *
- * @param The root rootView of the inflated layout
- */
- void onFinishInflate(IView rootView);
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/ILayoutInflater.java b/xml-inflater/src/main/java/com/itsaky/inflater/ILayoutInflater.java
deleted file mode 100644
index 2d377fbc5..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/ILayoutInflater.java
+++ /dev/null
@@ -1,185 +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.inflater;
-
-import android.content.Context;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.blankj.utilcode.util.FileIOUtils;
-import com.blankj.utilcode.util.FileUtils;
-import com.itsaky.inflater.util.Preconditions;
-
-import java.io.File;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A layout inflater which inflates layout from a raw XML file
- *
- * @author Akash Yadav
- */
-public abstract class ILayoutInflater {
-
- private static final Pattern XML_DECL = Pattern.compile("<\\?xml.*\\?>");
-
- /** The file whose content is currently being inflated. */
- private File currentlyInflatingFile;
-
- /**
- * Creates an instance of {@code ILayoutInflater}
- *
- * @param config The configuration of the LayoutInflater
- * @return A new layout inflater instance
- */
- @NonNull
- public static ILayoutInflater newInstance(LayoutInflaterConfiguration config) {
- return new XMLLayoutInflater(config);
- }
-
- /**
- * Reset the {@link ContextProvider} of this inflater
- *
- * @param provider The new {@link ContextProvider}
- */
- public abstract void resetContextProvider(ContextProvider provider);
-
- /**
- * Register the inflate listener to this inflater.
- *
- * NOTE: Do not register too much listeners as they may affect the inflation time.
- *
- * @param listener The listener to register.
- */
- public abstract void registerInflateListener(IInflateListener listener);
-
- /**
- * Unregister the inflate listener if it is registered.
- *
- * @param listener The listener to unregister
- */
- public abstract void unregisterListener(IInflateListener listener);
-
- /**
- * Inflate the layout from the given file path
- *
- * @param path The file path to inflate layout from
- * @return The inflated layout
- * @throws InflateException when there was an error inflating the layout
- */
- @NonNull
- public IView inflatePath(String path, ViewGroup parent) throws InflateException {
- Preconditions.assertNotBlank(path, "Layout file path is blank!");
- return inflate(new File(path), parent);
- }
-
- /**
- * Inflate the layout from the given file
- *
- * @param file The file to inflate layout from
- * @return The inflated layout
- * @throws InflateException when there was an error inflating the layout
- */
- @NonNull
- public IView inflate(File file, ViewGroup parent) throws InflateException {
-
- Preconditions.assertNotnull(file, "Cannot inflate null file");
-
- // How can we inflate a non existent file?
- if (!file.exists()) {
- throw new InflateException("File does not exist!");
- }
-
- if (!file.canRead()) {
- throw new InflateException("Cannot read file. Permission denied!");
- }
-
- // Cannot inflate a non UTF-8 too. This will also be true if the file is empty.
- if (!FileUtils.isUtf8(file)) {
- throw new InflateException("File is not UTF-8 or is empty!");
- }
-
- requireResourceTable().setInflatingFile(file);
- this.currentlyInflatingFile = file;
- return inflate(FileIOUtils.readFile2String(file), parent);
- }
-
- /**
- * Get the resource finder attached to this layout inflater.
- *
- * @return The attached resource finder.
- */
- @NonNull
- protected abstract IResourceTable requireResourceTable();
-
- /**
- * Inflate the layout from the provided XML layout code
- *
- * @param layout The XML layout code
- * @return The inflated layout
- * @throws InflateException when there was an error inflating the layout
- */
- @NonNull
- protected IView inflate(String layout, ViewGroup parent) throws InflateException {
-
- Preconditions.assertNotBlank(layout, "Layout is blank!");
-
- // Trim the layout code
- layout = layout.trim();
-
- final Matcher matcher = XML_DECL.matcher(layout);
- if (matcher.find()) {
- layout = layout.substring(matcher.end()).trim();
- }
-
- return doInflate(layout, parent);
- }
-
- /**
- * Acatual implementation of the layout inflation
- *
- * @param layout The layout to inflate
- * @return The inflated view
- * @throws InflateException when there was an error inflating the layout
- */
- @NonNull
- protected abstract IView doInflate(String layout, ViewGroup parent) throws InflateException;
-
- /**
- * Get the currently inflating file.
- *
- * @return The file.
- */
- @Nullable
- protected File getFile() {
- return currentlyInflatingFile;
- }
-
- /** Provides a reference to {@link Context}. This will be used to create original view. */
- public interface ContextProvider {
-
- /**
- * Provide the context to this inflater.
- *
- * @return The context
- */
- Context getContext();
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java b/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java
deleted file mode 100644
index 04cc64b3f..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java
+++ /dev/null
@@ -1,112 +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.inflater;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import java.io.File;
-import java.util.Collection;
-
-/** Finds values in resources of a project */
-public interface IResourceTable {
-
- /**
- * Find the path of the drawable with the provided name
- *
- *
This method will be called if the value of attribute starts with '@drawable/'
- *
- * @param name The name of the drawable
- * @return The drawable resource.
- */
- File findDrawable(@NonNull String name);
-
- /**
- * Find the layout file with the specified name.
- *
- * @param name The name of the layout file
- * @return The found layout resource file
- */
- File findLayout(@NonNull String name);
-
- /**
- * Find a string resource. Must be a valid string or {@code null}
- *
- * @param name The name of the resource
- * @return Value of the resource
- */
- String findString(@NonNull String name);
-
- /**
- * Find a color resource. The returned value must be a valid color value or {@code -1}
- *
- * @param name The name of the resource
- * @return Value of the resource
- */
- String findColor(@NonNull String name);
-
- /**
- * Find an array resource. Must be a valid array or {@code null}
- *
- * @param name The name of the resource
- * @return Value of the resource
- */
- String[] findArray(@NonNull String name);
-
- /**
- * Find the dimension value with the given name.
- *
- * @param name The name of the dimension resource
- * @return The String representation of the dimension. It could one of the following format : 1dp,
- * 12sp, 123px, etc.
- */
- String findDimension(@NonNull String name);
-
- /**
- * Find the boolean value with the given name.
- *
- * @param name The name of the boolean resource.
- * @return The string value of the boolean resource.
- */
- String findBoolean(@NonNull String name);
-
- /**
- * Find the integer value with the given name.
- *
- * @param name The name of the integer resource.
- * @return The string value of the integer resource.
- */
- String findInteger(@NonNull String name);
-
- /**
- * Set the file which is currently being inflated.
- *
- * @param file The file.
- */
- void setInflatingFile(@NonNull File file);
-
- /**
- * Lists the resources with the given type.
- *
- * @param type The type of the resources to list. Might be null.
- * @return A collection of resource names. If type is null, all the
- * resources in the resource table must be listed.
- */
- @NonNull
- Collection listResourceNames(@Nullable String type);
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IView.java b/xml-inflater/src/main/java/com/itsaky/inflater/IView.java
deleted file mode 100644
index e8b837c6c..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IView.java
+++ /dev/null
@@ -1,217 +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.inflater;
-
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.xml.INamespace;
-
-import java.util.List;
-
-/**
- * Represents a view in the UI Designer
- *
- * @author Akash Yadav
- */
-public interface IView {
-
- /**
- * The indentation length that will be used while generating layout code. You can modify this to
- * change the number of spaces used for indentation.
- */
- int DEFAULT_INDENTATION_LENGTH = 4;
-
- /**
- * Get this view as android {@link View}. This will be used to display this view in the designer
- *
- * @return {@link View} of this object. Maybe {@code null}
- */
- View asView();
-
- /**
- * Add this attribute to this view
- *
- * @param attr The Attribute to add
- */
- void addAttribute(IAttribute attr);
-
- /**
- * Remove this attribute
- *
- * @param attr The Attribute to remove
- */
- void removeAttribute(IAttribute attr);
-
- /**
- * Remove attribute at index
- *
- * @param index Index of the attribute to remove
- */
- void removeAttributeAt(int index);
-
- /**
- * Get the attributes of this view.
- *
- * @return The attributes.
- */
- List getAttributes();
-
- /**
- * Get the attributes of this view as an array.
- *
- * @return The attributes.
- * @see #getAttributes()
- */
- IAttribute[] getAttrArray();
-
- /**
- * Does this view contains an attribute with the given namespace and name?
- *
- * @param namespace The namespace to check.
- * @param name The name of the attribute to check.
- * @return {@code true} if this view contains the attribute, {@code false} otherwise.
- */
- boolean hasAttribute(INamespace namespace, String name);
-
- /**
- * Get the attribute with the given namespace and attribute name. Or {@code null} if there is no
- * attribute with the given namespace and name.s
- *
- * @param namespace The namespace of the attribute.
- * @param name The name of the attribute.
- * @return Found {@link IAttribute} or {@code null}.
- */
- @Nullable
- IAttribute getAttribute(INamespace namespace, String name);
-
- /**
- * Update the value of the given attribute.
- *
- * @param attribute The attribute that should be updated.
- * @return {@code true} if the attribute was successfully updated, {@code false} otherwise.
- */
- default boolean updateAttribute(@NonNull IAttribute attribute) {
- return updateAttribute(
- attribute.getNamespace(), attribute.getAttributeName(), attribute.getValue());
- }
-
- /**
- * Find and update the given attribute with the given value.
- *
- * @param namespace The namespace of the attribute.
- * @param name The name of the attribute.
- * @param value The new value of the attribute.
- * @return {@code true} if the attribute was successfully updated, {@code false} otherwise.
- */
- boolean updateAttribute(INamespace namespace, String name, String value);
-
- /**
- * Register this attribute adapter
- *
- * @param adapter The adapter to register
- */
- void registerAttributeAdapter(IAttributeAdapter adapter);
-
- /**
- * Register the given namespace to this view.
- *
- * @param namespace The name space to register.
- */
- void registerNamespace(INamespace namespace);
-
- /**
- * Find the namespace registered by the given name. Returns null if there is none.
- *
- * @param name The name of the namespace to look for. Must not be null.
- * @return The found namespace or null.
- */
- @Nullable
- INamespace findRegisteredNamespace(@NonNull String name);
-
- /**
- * Get the parent of this view
- *
- * @return The parent of this view or {@code null} if this is the root view.
- */
- IViewGroup getParent();
-
- /**
- * Set the parent of this view. This is set by {@link IViewGroup} when {@link
- * IViewGroup#addView(IView, int)} is called.
- *
- * @param newParent The new parent of this view.
- */
- void setParent(IViewGroup newParent);
-
- /**
- * Remove this view from its parent. This should take care of removing the actual {@link View}
- * from its parent.
- *
- * @return {@code true} if the view was successfully removed, {@code false} otherwise.
- */
- boolean removeFromParent();
-
- /**
- * Is this view a placeholder for another view?
- *
- * @return {@code true} if this view is a placeholder, {@code false} otherwise.
- */
- boolean isPlaceholder();
-
- /**
- * Get the stored data.
- *
- * @return The stored data.
- * @see #setExtraData(Object)
- */
- @Nullable
- Object getExtraData();
-
- /**
- * Store an object that is associated with this view.
- *
- * @param data The data to store.
- */
- void setExtraData(Object data);
-
- /**
- * @see #generateCode(int)
- */
- default String generateCode() {
- return generateCode(0);
- }
-
- /**
- * Get the layout resource code for this file.
- *
- * @param indentationLength The number of spaces to indent.
- */
- String generateCode(int indentationLength);
-
- /**
- * Get the tag name which will be used for generating XML Code for this view.
- *
- * Default implementation simply returns the simple name of this view's class.
- *
- * @return The tag name of this view.
- */
- String getXmlTag();
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IViewGroup.java b/xml-inflater/src/main/java/com/itsaky/inflater/IViewGroup.java
deleted file mode 100644
index f9146514d..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IViewGroup.java
+++ /dev/null
@@ -1,145 +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.inflater;
-
-import android.view.View;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-/**
- * Represents a {@link android.view.ViewGroup}
- *
- * @author Akash Yadav
- */
-public interface IViewGroup extends IView {
-
- /**
- * Add this view to this group
- *
- * @param view The view to add
- */
- void addView(IView view);
-
- /**
- * Add this view to this group
- *
- * @param view The view to add
- * @param index Add this view to this index
- */
- void addView(IView view, int index);
-
- /**
- * Remove the view at the specified index
- *
- * @param index The index of the view to remove
- */
- void removeView(int index);
-
- /**
- * Remove the given if it exists in this group
- *
- * @param view The view to remove
- */
- void removeView(IView view);
-
- /** Remove all children in this group */
- void removeAll();
-
- /**
- * Perform an action in every child in this group
- *
- * @param consumer The consumer which will consume the views
- */
- void forEachChild(Consumer consumer);
-
- /**
- * Get the number of child views this layout contains
- *
- * @return The child count
- */
- int getChildCount();
-
- /**
- * Get the list of children in this group
- *
- * @return The list of children
- */
- List getChildren();
-
- /**
- * Get child at the provided index
- *
- * @param index The index of child
- * @throws IndexOutOfBoundsException If there is no child at the given index
- */
- IView getChildAt(int index);
-
- /**
- * Find the index of the given children in this group.
- *
- * @param view The view to find index of.
- * @return The index of the child or -1 if this group does not contain the given child.
- */
- int indexOfChild(IView view);
-
- /**
- * Find the index of the given children in this group.
- *
- * @param view The view to find index of.
- * @return The index of the child or -1 if this group does not contain the given child.
- */
- int indexOfChild(View view);
-
- /**
- * Register the given hierarchy change listener to this group.
- *
- * @param listener The listener to register.
- */
- void registerHierarchyChangeListener(OnHierarchyChangeListener listener);
-
- /**
- * Unregister the given hierarchy change listener from this view group.
- *
- * @param listener The listener to unregister.
- */
- void unregisterHierarchyChangeListener(OnHierarchyChangeListener listener);
-
- /**
- * A listener which can be used to get notification when a children is added or removed from an
- * {@link IViewGroup}.
- *
- * @author Akash Yadav
- */
- public static interface OnHierarchyChangeListener {
-
- /**
- * Called when a child view is added in the view group to which this listener is attached.
- *
- * @param view The view that was added.
- */
- void onViewAdded(IView view);
-
- /**
- * Called when a child view is removed from the view group to which this listener is attached.
- *
- * @param view The view that was removed. Note that this view's parent will be null.
- */
- void onViewRemoved(IView view);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/InflateException.java b/xml-inflater/src/main/java/com/itsaky/inflater/InflateException.java
deleted file mode 100644
index ba23d584b..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/InflateException.java
+++ /dev/null
@@ -1,36 +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.inflater;
-
-/** Thrown when there was an error inflating the layout */
-public class InflateException extends RuntimeException {
-
- public InflateException(String message) {
- super(message);
- }
-
- public InflateException(Throwable th) {
- super(th);
- }
-
- public InflateException(String msg, Throwable th) {
- super(msg, th);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/LayoutInflaterConfiguration.java b/xml-inflater/src/main/java/com/itsaky/inflater/LayoutInflaterConfiguration.java
deleted file mode 100644
index 905417d99..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/LayoutInflaterConfiguration.java
+++ /dev/null
@@ -1,87 +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.inflater;
-
-import com.itsaky.attrinfo.AttrInfo;
-import com.itsaky.widgets.WidgetInfo;
-
-import java.io.File;
-import java.util.Set;
-
-/** Configuration for {@link ILayoutInflater} */
-public class LayoutInflaterConfiguration {
-
- final Set resDirs;
- final AttrInfo attrInfo;
- final WidgetInfo widgetInfo;
- final IResourceTable resFinder;
- final ILayoutInflater.ContextProvider contextProvider;
-
- public LayoutInflaterConfiguration(
- Set resDirs,
- AttrInfo attrInfo,
- WidgetInfo widgetInfo,
- IResourceTable resourceProvider,
- ILayoutInflater.ContextProvider contextProvider) {
- this.resDirs = resDirs;
- this.attrInfo = attrInfo;
- this.widgetInfo = widgetInfo;
- this.resFinder = resourceProvider;
- this.contextProvider = contextProvider;
- }
-
- /** A class that builds a {@link LayoutInflaterConfiguration} */
- public static class Builder {
-
- private Set resDirs;
- private AttrInfo attrInfo;
- private WidgetInfo widgetInfo;
- private IResourceTable resourceProvider;
- private ILayoutInflater.ContextProvider provider;
-
- public Builder setResourceDirectories(Set dirs) {
- this.resDirs = dirs;
- return this;
- }
-
- public Builder setAttrInfo(AttrInfo info) {
- this.attrInfo = info;
- return this;
- }
-
- public Builder setWidgetInfo(WidgetInfo info) {
- this.widgetInfo = info;
- return this;
- }
-
- public Builder setResourceFinder(IResourceTable provider) {
- this.resourceProvider = provider;
- return this;
- }
-
- public Builder setContextProvider(ILayoutInflater.ContextProvider provider) {
- this.provider = provider;
- return this;
- }
-
- public LayoutInflaterConfiguration create() {
- return new LayoutInflaterConfiguration(
- resDirs, attrInfo, widgetInfo, resourceProvider, provider);
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/NotSupportedException.java b/xml-inflater/src/main/java/com/itsaky/inflater/NotSupportedException.java
deleted file mode 100644
index 9efa61b87..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/NotSupportedException.java
+++ /dev/null
@@ -1,41 +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.inflater;
-
-/**
- * Exception thrown by inflaters and drawable parsers to indicate that the a specific view or tag is
- * not supported.
- *
- * @author Akash Yadav
- */
-public class NotSupportedException extends UnsupportedOperationException {
-
- public NotSupportedException() {}
-
- public NotSupportedException(String message) {
- super(message);
- }
-
- public NotSupportedException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public NotSupportedException(Throwable cause) {
- super(cause);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/XMLLayoutInflater.java b/xml-inflater/src/main/java/com/itsaky/inflater/XMLLayoutInflater.java
deleted file mode 100644
index 25895d92a..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/XMLLayoutInflater.java
+++ /dev/null
@@ -1,448 +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.inflater;
-
-import static com.itsaky.inflater.util.Preconditions.assertNotBlank;
-import static com.itsaky.inflater.util.Preconditions.assertNotnull;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.StringRes;
-
-import com.blankj.utilcode.util.ReflectUtils;
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.attrinfo.AttrInfo;
-import com.itsaky.inflater.adapters.android.view.ViewAttrAdapter;
-import com.itsaky.inflater.adapters.android.view.ViewGroupAttrAdapter;
-import com.itsaky.inflater.impl.BaseView;
-import com.itsaky.inflater.impl.ErrorUiView;
-import com.itsaky.inflater.impl.IncludeLayout;
-import com.itsaky.inflater.impl.UiAttribute;
-import com.itsaky.inflater.impl.UiView;
-import com.itsaky.inflater.impl.UiViewGroup;
-import com.itsaky.inflater.util.Preconditions;
-import com.itsaky.widgets.WidgetInfo;
-import com.itsaky.widgets.models.Widget;
-import com.itsaky.xml.INamespace;
-import com.itsaky.xml.impl.UiNamespace;
-
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Attribute;
-import org.jsoup.nodes.Attributes;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.parser.Parser;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.Objects;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-class XMLLayoutInflater extends BaseLayoutInflater {
-
- public static final String ATTR_ADAPTER_SUFFIX = "AttrAdapter";
- private static final ILogger LOG = ILogger.newInstance("XMLLayoutInflater");
- private final Set resDirs;
- private final AttrInfo attrInfo;
- private final WidgetInfo widgetInfo;
- private final IResourceTable resFinder;
- private ContextProvider contextProvider;
-
- XMLLayoutInflater(@NonNull LayoutInflaterConfiguration config) {
- this.resDirs = config.resDirs;
- this.attrInfo = config.attrInfo;
- this.widgetInfo = config.widgetInfo;
- this.resFinder = config.resFinder;
- this.contextProvider = config.contextProvider;
-
- Preconditions.assertAllNotNull(
- "LayoutInflater parameters cannot be null", resDirs, attrInfo, widgetInfo, resFinder);
- }
-
- @Override
- public void resetContextProvider(ILayoutInflater.ContextProvider provider) {
- this.contextProvider = provider;
- }
-
- @NonNull
- @Override
- protected IResourceTable requireResourceTable() {
- return this.resFinder;
- }
-
- @Override
- @NonNull
- protected IView doInflate(String layout, ViewGroup parent) throws InflateException {
- try {
-
- IDTable.newRound();
-
- // Notify
- preInflate();
-
- final Document doc = Jsoup.parse(layout, "", Parser.xmlParser());
-
- if (doc.childrenSize() <= 0) {
- throw new InflateException("No views added");
- }
-
- if (doc.childrenSize() > 1) {
- throw new InflateException(
- "More than one root element was found. An XML layout can have only one root"
- + " element.");
- }
-
- IView root = onCreateView(doc.child(0), parent, null);
-
- if (root == null) {
- root = onCreateErrorView(TextView.class.getName(), "No views added", parent);
- }
-
- // Notify
- postInflate(root);
-
- return root;
- } catch (Throwable th) {
- throw new InflateException("Unable to inflate layout", th);
- }
- }
-
- protected IView onCreateView(Element tag, ViewGroup parentGroup, IViewGroup parent)
- throws InflateException {
- if (tag == null) {
- return null;
- }
-
- final String name = tag.tagName().trim();
-
- if (name.equals("include")) {
- return createFromInclude(tag.attributes(), parent);
- }
-
- final IView root;
- int style = tag.hasAttr("style") ? parseFrameworkStyle(tag.attr("style")) : -1;
- if (!name.contains(".")) {
- root = createFromSimpleName(name, parentGroup, style);
- } else {
- root = createFromQualifiedName(name, parentGroup, style);
- }
-
- if (root == null) {
- return null;
- }
-
- registerAttributeAdaptersTo(root);
-
- if (!tag.attributes().isEmpty()) {
- addAttributesTo(root, tag.attributes(), parent);
- }
-
- if (root instanceof IViewGroup) {
- addChildren(tag, (IViewGroup) root);
- }
-
- postCreateView(root);
-
- return root;
- }
-
- protected void addChildren(@NonNull Element tag, IViewGroup parent) {
- if (tag.childrenSize() > 0 && !parent.isPlaceholder()) {
- for (Element child : tag.children()) {
- final IView created = onCreateView(child, (ViewGroup) parent.asView(), parent);
- if (created != null) {
- parent.addView(created);
- created.setParent(parent);
- }
- }
- }
- }
-
- protected int parseFrameworkStyle(String value) throws InflateException {
- try {
- final String name = underscorize(value.substring(value.indexOf('/') + 1));
- return (int) android.R.attr.class.getField(name).get(null);
- } catch (Throwable th) {
- LOG.error("Unable to parse framework style", th);
- return -1;
- }
- }
-
- protected void registerAttributeAdaptersTo(@NonNull IView root) {
- root.registerAttributeAdapter(onCreateAttributeAdapter(root.asView()));
- }
-
- protected IAttributeAdapter onCreateAttributeAdapter(View view) {
- final var displayMetrics = contextProvider.getContext().getResources().getDisplayMetrics();
- try {
- final String adapterName = view.getClass().getName().concat(ATTR_ADAPTER_SUFFIX);
- final String name = "com.itsaky.inflater.adapters.".concat(adapterName);
- final Class extends IAttributeAdapter> adapterClass =
- getClass().getClassLoader().loadClass(name).asSubclass(IAttributeAdapter.class);
- final var constructor =
- adapterClass.getConstructor(IResourceTable.class, DisplayMetrics.class);
- final var adapter = constructor.newInstance(resFinder, displayMetrics);
- adapter.setResourceFinder(resFinder);
- return adapter;
- } catch (Throwable th) {
- LOG.error(
- BaseApplication.getBaseInstance()
- .getString(
- com.itsaky.androidide.resources.R.string.err_no_attr_adapter, view.getClass().getName()),
- th);
- }
-
- // If we cannot find a suitable adapter, fall back to using common adapters
- IAttributeAdapter adapter;
- if (view instanceof ViewGroup) {
- adapter = new ViewGroupAttrAdapter(resFinder, displayMetrics);
- } else {
- adapter = new ViewAttrAdapter(resFinder, displayMetrics);
- }
- return adapter;
- }
-
- protected void addAttributesTo(IView view, Attributes attributes, IViewGroup parent) {
- assertNotnull(attributes, "Cannot apply null attributes!");
-
- for (Attribute attr : attributes) {
- final String key = attr.getKey();
- final String[] split =
- !key.contains(":") ? new String[] {"", key} : key.split(Pattern.quote(":"), 2);
- final String namespace = split[0];
- final String name = split[1];
- final String value = attr.getValue();
-
- INamespace ns;
- if (namespace.equals("xmlns")) {
- ns = INamespace.DECLARATOR;
- view.registerNamespace(new UiNamespace(name, value));
- } else {
- // set the parent so that we could look for
- // declared namespaces
- view.setParent(parent);
- ns = view.findRegisteredNamespace(namespace);
- }
-
- if (ns == null) {
- ns = INamespace.invalid(namespace);
- }
-
- final IAttribute iAttr = asAttribute(ns, name, value);
- view.addAttribute(iAttr);
-
- postApplyAttribute(iAttr, view);
- }
- }
-
- protected IAttribute asAttribute(INamespace namespace, String name, String value) {
- return new UiAttribute(namespace, name, value);
- }
-
- protected IView create(@NonNull String name, ViewGroup parent, int style)
- throws InflateException {
- if (!name.contains(".")) {
- return createFromSimpleName(name, parent, style);
- } else {
- return createFromQualifiedName(name, parent, style);
- }
- }
-
- protected IView createFromInclude(Attributes attrs, IViewGroup parent) {
-
- if (!attrs.hasKey("layout")) {
- throw new InflateException(" tag doesn't have 'layout' attribute.");
- }
-
- final var layout = attrs.get("layout");
- Preconditions.assertNotBlank(
- layout,
- "'layout' attribute for tag has invalid value." + "layout='" + layout + "'");
-
- if (layout.startsWith("@android:layout/")) {
- return inflateAndroidLayout(layout.substring("@android:layout/".length()), attrs, parent);
- }
-
- final var name = layout.substring("@layout/".length());
- final var file = resFinder.findLayout(name);
- if (file == null) {
- throw new InflateException("Layout file '" + name + "' not found");
- }
-
- return inflateLocalIncludeLayout(attrs, parent, name, file);
- }
-
- protected IView inflateAndroidLayout(String name, Attributes attrs, @NonNull IViewGroup parent) {
- final var id = (int) ReflectUtils.reflect(android.R.layout.class).field(name).get();
- final var view = LayoutInflater.from(contextProvider.getContext()).inflate(id, null);
- final var layout = new IncludeLayout(new UiView(IncludeLayout.TAG, view, false));
-
- applyLayoutParams(layout, (ViewGroup) parent.asView());
- addAttributesTo(layout, attrs, parent);
-
- return layout;
- }
-
- protected IView createFromSimpleName(String name, ViewGroup parent, int style)
- throws InflateException {
- final Widget widget = widgetInfo.getWidgetBySimpleName(name);
- if (widget == null) {
- LOG.error("Unable to inflate view. widget == null");
- return onCreateErrorView(
- name, getString(com.itsaky.androidide.resources.R.string.msg_cannot_create_view, name), parent);
- }
-
- return createFromQualifiedName(widget.name, parent, style);
- }
-
- protected IView createFromQualifiedName(String name, ViewGroup parent, int style)
- throws InflateException {
- assertNotBlank(name, "Invalid tag name: " + name);
-
- // TODO Try to load classes directly from .class files if possible
- try {
-
- final var androidView = this.widgetInfo.getWidget(name);
- if (androidView == null) {
- // If this is not an Android view, do not bother to create one
- throw new NotSupportedException();
- }
-
- final View created = createAndroidViewForName(name, style);
- final BaseView view =
- created instanceof ViewGroup
- ? new UiViewGroup(name, (ViewGroup) created)
- : new UiView(name, created);
- return applyLayoutParams(view, parent);
- } catch (Throwable th) {
-
- if (th instanceof NotSupportedException) {
- return onCreateErrorView(name, getString(R.string.msg_view_not_supported, name), parent);
- }
-
- final var msg = getString(R.string.msg_cannot_create_view, name);
- LOG.error(msg, th);
- return onCreateErrorView(name, msg, parent);
- }
- }
-
- @NonNull
- protected View createAndroidViewForName(String name, int style)
- throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
- InstantiationException, java.lang.reflect.InvocationTargetException {
- final Class extends View> loaded = Class.forName(name).asSubclass(View.class);
- final Constructor extends View> constructor;
- if (style == -1) {
- constructor = loaded.getConstructor(Context.class);
- return constructor.newInstance(contextProvider.getContext());
- } else {
- constructor = loaded.getConstructor(Context.class, AttributeSet.class, int.class);
- return constructor.newInstance(contextProvider.getContext(), null, style);
- }
- }
-
- protected IView applyLayoutParams(@NonNull IView view, ViewGroup parent) {
- final ViewGroup.LayoutParams params = generateLayoutParams(parent);
- view.asView().setLayoutParams(params);
- return view;
- }
-
- protected IView onCreateErrorView(String name, String msg, final ViewGroup parent)
- throws InflateException {
- final var view =
- ErrorUiView.create(
- Objects.requireNonNull(contextProvider.getContext(), "Context is null."), name, msg);
- return applyLayoutParams(view, parent);
- }
-
- @NonNull
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup parent) {
- try {
- Class> clazz = parent.getClass();
- Method method = null;
-
- while (true) {
- try {
- method = clazz.getDeclaredMethod("generateDefaultLayoutParams");
- break;
- } catch (Throwable e) {
- /* ignored */
- }
- clazz = clazz.getSuperclass();
-
- if (clazz == null) {
- break;
- }
- }
-
- if (method != null) {
- method.setAccessible(true);
- return (ViewGroup.LayoutParams) method.invoke(parent);
- }
-
- LOG.error("Unable to create default params for view parent:", parent);
- return new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
- } catch (Throwable th) {
- throw new InflateException("Unable to create layout params for parent: " + parent, th);
- }
- }
-
- @NonNull
- private String underscorize(@NonNull String substring) {
- return substring.replace(".", "_");
- }
-
- @NonNull
- private IncludeLayout inflateLocalIncludeLayout(
- Attributes attrs, IViewGroup parent, String name, File file) {
-
- // DesignerActivity applies drag listeners in 'onInflateView()' call
- // But, layouts must not be edited here
- // So, we avoid notifying the listeners
- super.notify = false;
-
- final var view = this.inflate(file, (ViewGroup) parent.asView());
- Preconditions.assertNotnull(view, "Failed to inflate '" + name + "'");
-
- final var includeLayout = new IncludeLayout(view);
-
- applyLayoutParams(includeLayout, (ViewGroup) parent.asView());
- addAttributesTo(includeLayout, attrs, parent);
-
- // Enable notifications
- super.notify = true;
-
- return includeLayout;
- }
-
- private String getString(@StringRes int id, Object... format) throws InflateException {
- assertNotnull(contextProvider.getContext(), "Context is null!");
- return contextProvider.getContext().getString(id, format);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/README.md b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/README.md
deleted file mode 100644
index 06f82aba4..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/README.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Attribute Adapters
-
-Attribute adapters handle attributes for a specific view.
-
-## Implementing an Adapter
-
-### Basic
-
-To implment an adapter, you'll have to write a class extending one of the existing adapters.
-
-Adapters extend other adapters in the same way as Android's view classes extend other views. For
-example, ```android.widget.CompoundButton``` extends ```android.widget.Button```, in the same way
-```com.itsaky.layoutinflater.adapters.android.widget.CompoundButtonAttrAdapter``` extends
-```com.itsaky.layoutinflater.adapters.android.widget.ButtonAttrAdapter```. In this way, we don't
-have to rewrite whole logic again to implement adapters for every other widget.
-
-### Naming an adapter
-
-If you look at the package name and the simple name of the adapter classes mentioned above, you'll
-find that there is a specific way an adapter is named.
-
-An adpater should be named in the following way :
-```com.itsaky.layoutinflater.adapters..AttrAdapter```,
-where, `````` is the package name of the widget you are implementing an adapter for
-and `````` is the simple name of the widget. The simple name is then suffixed
-with ```AttrAdapter```.
-
-Here is an example :
-Assume we have to implement an adapter for ```android.widget.Button```. Here, ``````
-is ```android.widget``` and
-`````` is ```Button```.
-
-So, the adapter implentation class should
-be ```com.itsaky.layoutinflater.adapters.android.widget.ButtonAttrAdapter```.
-
-### Why such naming?
-
-We use reflection to automatically create an adapter when inflating a view. For example,
-if ```android.widget.Button``` instance is being created, we could simply create an adapter instance
-using reflection by getting the package name and simple name of the widget.
-
-See ```XMLLayoutInflater#onCreateAttributeAdapter(View)```.
-
-### Precautions
-
-- Make sure you correctly spell the file names. As you might already know, file names are case
- sensitive.
-- Some methods (or even classes) are not available for earlier versions of Android. The classes or
- methods you're using must be compatible with API 24.
-
-You could also check if you can use a method. Some methods are already implemented in
-ViewAttrAdapter so you won't have to rewrite them. For example:
-
-```
-isApi26() // Android 8 (Oreo)
-isApi28() // Android 9 (Pie)
-isApi29() // Android 10 (Q)
-isApi30() // Android 11 (R)
-```
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/gesture/GestureOverlayViewAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/gesture/GestureOverlayViewAttrAdapter.java
deleted file mode 100644
index 639af086b..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/gesture/GestureOverlayViewAttrAdapter.java
+++ /dev/null
@@ -1,121 +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.inflater.adapters.android.gesture;
-
-import android.gesture.GestureOverlayView;
-import android.util.DisplayMetrics;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-
-import com.blankj.utilcode.util.ReflectUtils;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.widget.FrameLayoutAttrAdapter;
-
-/**
- * Attribute adapter for {@link GestureOverlayView}
- *
- * @author Akash Yadav
- */
-public class GestureOverlayViewAttrAdapter extends FrameLayoutAttrAdapter {
-
- public GestureOverlayViewAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof GestureOverlayView;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var gesture = (GestureOverlayView) view;
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "eventsInterceptionEnabled":
- gesture.setEventsInterceptionEnabled(parseBoolean(value));
- break;
- case "fadeDuration":
- ReflectUtils.reflect(gesture).field("mFadeDuration", parseLong(value, 150));
- break;
- case "fadeEnabled":
- gesture.setFadeEnabled(parseBoolean(value));
- break;
- case "fadeOffset":
- gesture.setFadeOffset(parseLong(value, 420));
- break;
- case "gestureColor":
- gesture.setGestureColor(parseColor(value, gesture.getContext()));
- break;
- case "gestureStrokeAngleThreshold":
- gesture.setGestureStrokeAngleThreshold(parseFloat(value));
- break;
- case "gestureStrokeLengthThreshold":
- gesture.setGestureStrokeLengthThreshold(parseFloat(value));
- break;
- case "gestureStrokeSquarenessThreshold":
- gesture.setGestureStrokeSquarenessTreshold(parseFloat(value));
- break;
- case "gestureStrokeType":
- gesture.setGestureStrokeType(parseGestureStrokeType(value));
- break;
- case "gestureStrokeWidth":
- gesture.setGestureStrokeWidth(parseFloat(value));
- break;
- case "orientation":
- gesture.setOrientation(parseOrientation(value));
- break;
- case "uncertainGestureColor":
- gesture.setUncertainGestureColor(parseColor(value, gesture.getContext()));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-
- private int parseOrientation(String value) {
- if ("horizontal".equals(value)) {
- return GestureOverlayView.ORIENTATION_HORIZONTAL;
- }
-
- return GestureOverlayView.ORIENTATION_VERTICAL;
- }
-
- protected int parseGestureStrokeType(String value) {
- if ("multiple".equals(value)) {
- return GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE;
- }
- return GestureOverlayView.GESTURE_STROKE_TYPE_SINGLE;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/view/ViewAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/view/ViewAttrAdapter.java
deleted file mode 100644
index c073a7571..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/view/ViewAttrAdapter.java
+++ /dev/null
@@ -1,595 +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.inflater.adapters.android.view;
-
-import android.content.Context;
-import android.graphics.PorterDuff;
-import android.os.Build;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-
-import androidx.annotation.ChecksSdkIntAtLeast;
-import androidx.annotation.NonNull;
-
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IAttributeAdapter;
-import com.itsaky.inflater.IDTable;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.util.CommonParseUtils;
-import com.itsaky.xml.INamespace;
-
-/**
- * Handles attributes common to all android views. Also, LayoutParams related issues are also
- * handled by this adapter.
- *
- * @author Akash Yadav
- */
-public class ViewAttrAdapter extends CommonParseUtils implements IAttributeAdapter {
-
- protected static final ILogger LOG = ILogger.newInstance("BaseViewAttrAdapter");
-
- public ViewAttrAdapter(@NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public void setResourceFinder(IResourceTable resourceFinder) {
- this.resourceFinder = resourceFinder;
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return true; // Can be applied to any view
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final INamespace namespace = attribute.getNamespace();
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
- final ViewGroup.LayoutParams params = view.getLayoutParams();
- final Context context = view.getContext();
-
- if (!canHandleNamespace(namespace)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "layout_height":
- params.height = parseDimension(value, -2, displayMetrics);
- break;
- case "layout_width":
- params.width = parseDimension(value, -2, displayMetrics);
- break;
- case "alpha":
- view.setAlpha(parseFloat(value));
- break;
- case "background":
- view.setBackground(parseDrawable(value, context));
- break;
- case "backgroundTint":
- view.setBackgroundTintList(parseColorStateList(value, context));
- break;
- case "backgroundTintMode":
- view.setBackgroundTintMode(parsePorterDuffMode(value));
- break;
- case "clipToOutline":
- view.setClipToOutline(parseBoolean(value));
- break;
- case "contentDescription":
- view.setContentDescription(parseString(value));
- break;
- case "contextClickable":
- view.setContextClickable(parseBoolean(value));
- break;
- case "defaultFocusHighlightEnabled":
- view.setDefaultFocusHighlightEnabled(parseBoolean(value));
- break;
- case "drawingCacheQuality":
- view.setDrawingCacheQuality(parseDrawingCacheQuality(value));
- break;
- case "duplicateParentState":
- view.setDuplicateParentStateEnabled(parseBoolean(value));
- break;
- case "elevation":
- view.setElevation(parseDimension(value, 0, displayMetrics));
- break;
- case "fadeScrollbars":
- view.setScrollbarFadingEnabled(parseBoolean(value));
- break;
- case "fadingEdgeLength":
- view.setFadingEdgeLength(parseDimension(value, 0, displayMetrics));
- break;
- case "filterTouchesWhenObscured":
- view.setFilterTouchesWhenObscured(parseBoolean(value));
- break;
- case "foreground":
- view.setForeground(parseDrawable(value, context));
- break;
- case "foregroundGravity":
- view.setForegroundGravity(parseGravity(value));
- break;
- case "foregroundTint":
- view.setForegroundTintList(parseColorStateList(value, context));
- break;
- case "foregroundTintMode":
- view.setForegroundTintMode(parsePorterDuffMode(value));
- break;
- case "id":
- view.setId(parseId(value));
- break;
- case "minHeight":
- view.setMinimumHeight(parseDimension(value, 0, displayMetrics));
- break;
- case "minWidth":
- view.setMinimumWidth(parseDimension(value, 0, displayMetrics));
- break;
- case "padding":
- final int padding = parseDimension(value, 0, displayMetrics);
- view.setPaddingRelative(padding, padding, padding, padding);
- break;
- case "paddingLeft":
- final int paddingLeft = parseDimension(value, 0, displayMetrics);
- view.setPadding(
- paddingLeft, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom());
- break;
- case "paddingTop":
- final int paddingTop = parseDimension(value, 0, displayMetrics);
- view.setPadding(
- view.getPaddingLeft(), paddingTop, view.getPaddingRight(), view.getPaddingBottom());
- break;
- case "paddingRight":
- final int paddingRight = parseDimension(value, 0, displayMetrics);
- view.setPadding(
- view.getPaddingLeft(), view.getPaddingTop(), paddingRight, view.getPaddingBottom());
- break;
- case "paddingBottom":
- final int paddingBottom = parseDimension(value, 0, displayMetrics);
- view.setPadding(
- view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), paddingBottom);
- break;
- case "paddingStart":
- final int paddingStart = parseDimension(value, 0, displayMetrics);
- view.setPaddingRelative(
- paddingStart, view.getPaddingTop(), view.getPaddingEnd(), view.getPaddingBottom());
- break;
- case "paddingEnd":
- final int paddingEnd = parseDimension(value, 0, displayMetrics);
- view.setPaddingRelative(
- view.getPaddingStart(), view.getPaddingTop(), paddingEnd, view.getPaddingBottom());
- break;
- case "rotation":
- view.setRotation(parseFloat(value));
- break;
- case "rotationX":
- view.setRotationX(parseFloat(value));
- break;
- case "rotationY":
- view.setRotationY(parseFloat(value));
- break;
- case "scaleX":
- view.setScaleX(parseFloat(value));
- break;
- case "scaleY":
- view.setScaleY(parseFloat(value));
- break;
- case "scrollX":
- view.setScrollX((int) parseFloat(value));
- break;
- case "scrollY":
- view.setScrollY((int) parseFloat(value));
- break;
- case "textAlignment":
- view.setTextAlignment(parseTextAlignment(value));
- break;
- case "textDirection":
- view.setTextDirection(parseTextDirection(value));
- break;
- case "tooltipText":
- view.setTooltipText(parseString(value));
- break;
- case "transformPivotX":
- view.setPivotX(parseFloat(value));
- break;
- case "transformPivotY":
- view.setPivotY(parseFloat(value));
- break;
- case "translationX":
- view.setTranslationX(parseFloat(value));
- break;
- case "translationY":
- view.setTranslationY(parseFloat(value));
- break;
- case "translationZ":
- view.setTranslationZ(parseFloat(value));
- break;
- case "visibility":
- view.setVisibility(parseVisibility(value));
- break;
- default:
- handled = false;
- break;
- }
-
- // ----- Handle attributes related to parent ------
-
- if (!handled && params instanceof LinearLayout.LayoutParams) {
- handled =
- handleLinearLayoutParams((LinearLayout.LayoutParams) params, name, value, displayMetrics);
- }
-
- if (!handled && params instanceof RelativeLayout.LayoutParams) {
- handled = handleRelativeLayoutParams((RelativeLayout.LayoutParams) params, name, value);
- }
-
- if (!handled && params instanceof FrameLayout.LayoutParams) {
- handled = handleFrameLayoutParams((FrameLayout.LayoutParams) params, name, value);
- }
-
- if (!handled && params instanceof ViewGroup.MarginLayoutParams) {
- handled =
- handleMarginParams((ViewGroup.MarginLayoutParams) params, name, value, displayMetrics);
- }
-
- view.setLayoutParams(params);
-
- return handled;
- }
-
- protected int parseId(@NonNull String value) {
- if (value.startsWith("@id/")) {
- final String name = value.substring("@id/".length());
- return IDTable.getId(name);
- } else if (value.startsWith("@+id/")) {
- final String name = value.substring("@+id/".length());
- return IDTable.newId(name);
- }
- return View.NO_ID;
- }
-
- protected boolean handleRelativeLayoutParams(
- RelativeLayout.LayoutParams params, @NonNull String name, String value) {
- boolean handled = true;
- switch (name) {
- case "layout_above":
- params.addRule(RelativeLayout.ABOVE, parseId(value));
- break;
- case "layout_alignBaseline":
- params.addRule(RelativeLayout.ALIGN_BASELINE, parseId(value));
- break;
- case "layout_alignBottom":
- params.addRule(RelativeLayout.ALIGN_BOTTOM, parseId(value));
- break;
- case "layout_alignEnd":
- params.addRule(RelativeLayout.ALIGN_END, parseId(value));
- break;
- case "layout_alignLeft":
- params.addRule(RelativeLayout.ALIGN_LEFT, parseId(value));
- break;
- case "layout_alignParentTop":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.ALIGN_PARENT_TOP, params);
- break;
- case "layout_alignParentBottom":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.ALIGN_PARENT_BOTTOM, params);
- break;
- case "layout_alignParentStart":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.ALIGN_PARENT_START, params);
- break;
- case "layout_alignParentEnd":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.ALIGN_PARENT_END, params);
- break;
- case "layout_alignParentLeft":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.ALIGN_PARENT_LEFT, params);
- break;
- case "layout_alignParentRight":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.ALIGN_PARENT_RIGHT, params);
- break;
- case "layout_alignRight":
- params.addRule(RelativeLayout.ALIGN_RIGHT, parseId(value));
- break;
- case "layout_alignStart":
- params.addRule(RelativeLayout.ALIGN_START, parseId(value));
- break;
- case "layout_alignTop":
- params.addRule(RelativeLayout.ALIGN_TOP, parseId(value));
- break;
- case "layout_alignWithParentIfMissing":
- params.alignWithParent = parseBoolean(value);
- break;
- case "layout_below":
- params.addRule(RelativeLayout.BELOW, parseId(value));
- break;
- case "layout_centerHorizontal":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.CENTER_HORIZONTAL, params);
- break;
- case "layout_centerInParent":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.CENTER_IN_PARENT, params);
- break;
- case "layout_centerVertical":
- setRelativeRuleIfTrue(parseBoolean(value), RelativeLayout.CENTER_VERTICAL, params);
- break;
- case "layout_toEndOf":
- params.addRule(RelativeLayout.END_OF, parseId(value));
- break;
- case "layout_toStartOf":
- params.addRule(RelativeLayout.START_OF, parseId(value));
- break;
- case "layout_toLeftOf":
- params.addRule(RelativeLayout.LEFT_OF, parseId(value));
- break;
- case "layout_toRightOf":
- params.addRule(RelativeLayout.RIGHT_OF, parseId(value));
- break;
- default:
- handled = false;
- }
- return handled;
- }
-
- protected boolean handleLinearLayoutParams(
- LinearLayout.LayoutParams params, @NonNull String name, String value, DisplayMetrics dm) {
- boolean handled = true;
- switch (name) {
- case "layout_gravity":
- params.gravity = parseGravity(value);
- break;
- case "layout_weight":
- params.weight = parseDimension(value, 1, dm);
- break;
- default:
- handled = false;
- break;
- }
- return handled;
- }
-
- protected boolean handleFrameLayoutParams(
- FrameLayout.LayoutParams params, @NonNull String name, String value) {
- boolean handled = true;
-
- if ("layout_gravity".equals(name)) {
- params.gravity = parseGravity(value);
- } else {
- handled = false;
- }
-
- return handled;
- }
-
- protected boolean handleMarginParams(
- ViewGroup.MarginLayoutParams params, @NonNull String name, String value, DisplayMetrics dm) {
- boolean handled = true;
- switch (name) {
- case "layout_margin":
- final int margin = parseDimension(value, 0, dm);
- params.setMargins(margin, margin, margin, margin);
- break;
- case "layout_marginLeft":
- params.leftMargin = parseDimension(value, 0, dm);
- break;
- case "layout_marginTop":
- params.topMargin = parseDimension(value, 0, dm);
- break;
- case "layout_marginRight":
- params.rightMargin = parseDimension(value, 0, dm);
- break;
- case "layout_marginBottom":
- params.bottomMargin = parseDimension(value, 0, dm);
- break;
- case "layout_marginStart":
- params.setMarginStart(parseDimension(value, 0, dm));
- break;
- case "layout_marginEnd":
- params.setMarginEnd(parseDimension(value, 0, dm));
- break;
- default:
- handled = false;
- break;
- }
-
- return handled;
- }
-
- protected boolean canHandleNamespace(@NonNull IAttribute attr) {
- return canHandleNamespace(attr.getNamespace());
- }
-
- protected boolean canHandleNamespace(INamespace namespace) {
- return INamespace.ANDROID.equals(namespace);
- }
-
- protected int parseDrawingCacheQuality(@NonNull String value) {
- switch (value) {
- case "high":
- return View.DRAWING_CACHE_QUALITY_HIGH;
- case "low":
- return View.DRAWING_CACHE_QUALITY_LOW;
- case "auto":
- default:
- return View.DRAWING_CACHE_QUALITY_AUTO;
- }
- }
-
- protected int parseVisibility(@NonNull String value) {
- switch (value) {
- case "gone":
- return View.GONE;
- case "invisible":
- return View.INVISIBLE;
- case "visible":
- default:
- return View.VISIBLE;
- }
- }
-
- protected int parseTextAlignment(@NonNull String value) {
- switch (value) {
- case "center":
- return View.TEXT_ALIGNMENT_CENTER;
- case "gravity":
- return View.TEXT_ALIGNMENT_GRAVITY;
- case "textEnd":
- return View.TEXT_ALIGNMENT_TEXT_END;
- case "textStart":
- return View.TEXT_ALIGNMENT_TEXT_START;
- case "viewEnd":
- return View.TEXT_ALIGNMENT_VIEW_END;
- case "viewStart":
- return View.TEXT_ALIGNMENT_VIEW_START;
- case "inherit":
- default:
- return View.TEXT_ALIGNMENT_INHERIT;
- }
- }
-
- protected int parseTextDirection(@NonNull String value) {
- switch (value) {
- case "anyRtl":
- return View.TEXT_DIRECTION_ANY_RTL;
- case "firstStrong":
- return View.TEXT_DIRECTION_FIRST_STRONG;
- case "firstStrongLtr":
- return View.TEXT_DIRECTION_FIRST_STRONG_LTR;
- case "firstStrongRtl":
- return View.TEXT_DIRECTION_FIRST_STRONG_RTL;
- case "locale":
- return View.TEXT_DIRECTION_LOCALE;
- case "ltr":
- return View.TEXT_DIRECTION_LTR;
- case "rtl":
- return View.TEXT_DIRECTION_RTL;
- case "inherit":
- default:
- return View.TEXT_DIRECTION_INHERIT;
- }
- }
-
- protected PorterDuff.Mode parsePorterDuffMode(@NonNull String mode) {
- switch (mode) {
- case "add":
- return PorterDuff.Mode.ADD;
- case "multiply":
- return PorterDuff.Mode.MULTIPLY;
- case "screen":
- return PorterDuff.Mode.SCREEN;
- case "src_atop":
- return PorterDuff.Mode.SRC_ATOP;
- case "src_in":
- return PorterDuff.Mode.SRC_IN;
- case "src_over":
- return PorterDuff.Mode.SRC_OVER;
- default:
- return PorterDuff.Mode.SRC;
- }
- }
-
- protected float parseFloat(String value) {
- try {
- return Float.parseFloat(value);
- } catch (Throwable th) {
- return 1f;
- }
- }
-
- protected float parseFloat(String value, float def) {
- try {
- return Float.parseFloat(value);
- } catch (Throwable th) {
- return def;
- }
- }
-
- protected long parseLong(String value, long def) {
- try {
- return Long.parseLong(value);
- } catch (Throwable th) {
- return def;
- }
- }
-
- protected int parseDimension(final String value, int defaultValue, final DisplayMetrics dm) {
-
- if (value == null) {
- return defaultValue;
- }
-
- char c = value.charAt(0);
- if (Character.isDigit(c)) {
- // A dimension value which starts with a digit. E.g.: 1dp, 12sp, 123px, etc.
- StringBuilder dimensionVal = new StringBuilder();
- int index = 0;
- while (index < value.length() && Character.isDigit(c = value.charAt(index))) {
- dimensionVal.append(c);
- index++;
- }
-
- final int dimen = Integer.parseInt(dimensionVal.toString());
- final String dimensionType = value.substring(index);
- return (int) TypedValue.applyDimension(getUnitForDimensionType(dimensionType), dimen, dm);
- } else if (c == '@') {
- String name = value.substring("@dimen/".length());
- return parseDimension(resourceFinder.findDimension(name), defaultValue, dm);
- } else if (Character.isLetter(c)) {
- // This could be one of the following :
- // 1. match_parent
- // 2. wrap_content
- // 3. fill_parent
- switch (value) {
- case "match_parent":
- case "fill_parent":
- return ViewGroup.LayoutParams.MATCH_PARENT;
- case "wrap_content":
- default:
- return ViewGroup.LayoutParams.WRAP_CONTENT;
- }
- }
-
- return defaultValue;
- }
-
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.P)
- protected boolean isApi28() {
- return Build.VERSION.SDK_INT >= 28;
- }
-
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.Q)
- protected boolean isApi29() {
- return Build.VERSION.SDK_INT >= 29;
- }
-
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.R)
- protected boolean isApi30() {
- return Build.VERSION.SDK_INT >= 30;
- }
-
- private void setRelativeRuleIfTrue(
- boolean condition, int rule, RelativeLayout.LayoutParams params) {
- if (condition) {
- params.addRule(rule);
- } else {
- params.removeRule(rule);
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/view/ViewGroupAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/view/ViewGroupAttrAdapter.java
deleted file mode 100644
index 747c51b52..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/view/ViewGroupAttrAdapter.java
+++ /dev/null
@@ -1,111 +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.inflater.adapters.android.view;
-
-import android.animation.LayoutTransition;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-import org.jetbrains.annotations.Contract;
-
-/**
- * An attribute adapter implementation for ViewGroups.
- *
- * @author Akash Yadav
- */
-public class ViewGroupAttrAdapter extends ViewAttrAdapter {
-
- public ViewGroupAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof ViewGroup;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
-
- final ViewGroup group = (ViewGroup) view;
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "animateLayoutChanges":
- group.setLayoutTransition(new LayoutTransition());
- break;
- case "clipChildren":
- group.setClipChildren(parseBoolean(value));
- break;
- case "clipToPadding":
- group.setClipToPadding(parseBoolean(value));
- break;
- case "descendantFocusability":
- group.setDescendantFocusability(parseDescendantsFocusability(value));
- break;
- case "layoutMode":
- group.setLayoutMode(parseLayoutMode(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-
- @Contract(pure = true)
- private int parseLayoutMode(String value) {
- switch (value) {
- case "opticalBounds":
- return ViewGroup.LAYOUT_MODE_OPTICAL_BOUNDS;
- case "clipBounds":
- default:
- return ViewGroup.LAYOUT_MODE_CLIP_BOUNDS;
- }
- }
-
- protected int parseDescendantsFocusability(@NonNull String value) {
- switch (value) {
- case "beforeDescendants":
- return ViewGroup.FOCUS_BEFORE_DESCENDANTS;
- case "blocksDescendants":
- return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
- case "afterDescendants":
- default:
- return ViewGroup.FOCUS_AFTER_DESCENDANTS;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsListViewAttrAdapter.kt b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsListViewAttrAdapter.kt
deleted file mode 100644
index 314a8ba73..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsListViewAttrAdapter.kt
+++ /dev/null
@@ -1,84 +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.inflater.adapters.android.widget
-
-import android.util.DisplayMetrics
-import android.view.View
-import android.widget.AbsListView
-import com.itsaky.inflater.IAttribute
-import com.itsaky.inflater.IResourceTable
-
-/**
- * Attribute adapter for the [AbsListView] widget.
- *
- * @author Akash Yadav
- */
-open class AbsListViewAttrAdapter(resourceTable: IResourceTable, displayMetrics: DisplayMetrics) :
- AdapterViewAttrAdapter(resourceTable, displayMetrics) {
-
- override fun isApplicableTo(view: View?): Boolean {
- return view is AbsListView
- }
-
- override fun apply(attribute: IAttribute, view: View): Boolean {
- val list = view as AbsListView
- val context = list.context
- val value = attribute.value
-
- if (!canHandleNamespace(attribute)) {
- return false
- }
-
- var handled = true
- when (attribute.attributeName) {
- "cacheColorHint" -> list.cacheColorHint = parseColor(value, context)
- "choiceMode" -> list.choiceMode = parseChoiceMode(value)
- "drawSelectorOnTop" -> list.isDrawSelectorOnTop = parseBoolean(value)
- "fastScrollEnabled" -> list.isFastScrollEnabled = parseBoolean(value)
- "listSelector" -> list.selector = parseDrawable(value, context)
- "smoothScrollbar" -> list.isSmoothScrollbarEnabled = parseBoolean(value)
- "stackFromBottom" -> list.isStackFromBottom = parseBoolean(value)
- "textFilterEnabled" -> list.isTextFilterEnabled = parseBoolean(value)
- "transcriptMode" -> list.transcriptMode = parseTranscriptMode(value)
- else -> handled = false
- }
-
- if (!handled) {
- handled = super.apply(attribute, view)
- }
-
- return handled
- }
-
- protected open fun parseTranscriptMode(value: String): Int {
- return when (value) {
- "normal" -> AbsListView.TRANSCRIPT_MODE_NORMAL
- "alwaysScroll" -> AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL
- else -> AbsListView.TRANSCRIPT_MODE_DISABLED
- }
- }
-
- protected open fun parseChoiceMode(value: String): Int {
- return when (value) {
- "multipleChoice" -> AbsListView.CHOICE_MODE_MULTIPLE
- "multipleChoiceModal" -> AbsListView.CHOICE_MODE_MULTIPLE_MODAL
- "singleChoice" -> AbsListView.CHOICE_MODE_SINGLE
- else -> AbsListView.CHOICE_MODE_NONE
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsSeekBarAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsSeekBarAttrAdapter.java
deleted file mode 100644
index d733aeb98..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsSeekBarAttrAdapter.java
+++ /dev/null
@@ -1,83 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.AbsSeekBar;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute adapter for handling attributes related to AbsSeekBar.
- *
- * @author Akash Yadav
- */
-public abstract class AbsSeekBarAttrAdapter extends ProgressBarAttrAdapter {
-
- public AbsSeekBarAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof AbsSeekBar;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var seek = (AbsSeekBar) view;
- final var namespace = attribute.getNamespace();
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(namespace)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "thumbTint":
- seek.setThumbTintList(parseColorStateList(value, seek.getContext()));
- break;
- case "thumbTintMode":
- seek.setThumbTintMode(parsePorterDuffMode(value));
- break;
- case "tickMarkTint":
- seek.setTickMarkTintList(parseColorStateList(value, seek.getContext()));
- break;
- case "tickMarkTintMode":
- seek.setTickMarkTintMode(parsePorterDuffMode(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsSpinnerAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsSpinnerAttrAdapter.java
deleted file mode 100644
index 2eb4f9ac1..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AbsSpinnerAttrAdapter.java
+++ /dev/null
@@ -1,73 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.AbsSpinner;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-public class AbsSpinnerAttrAdapter extends AdapterViewAttrAdapter {
-
- public AbsSpinnerAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof AbsSpinner;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var spinner = (AbsSpinner) view;
- final var context = spinner.getContext();
- final var namespace = attribute.getNamespace();
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- boolean handled = true;
-
- if (!canHandleNamespace(namespace)) {
- return false;
- }
-
- switch (name) {
- case "entries":
- final var array = parseArray(value);
- final var adapter = newSimpleAdapter(context, array);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spinner.setAdapter(adapter);
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AdapterViewAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AdapterViewAttrAdapter.java
deleted file mode 100644
index 133b25380..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/AdapterViewAttrAdapter.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.inflater.adapters.android.widget;
-
-import android.content.Context;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewGroupAttrAdapter;
-
-/**
- * Adapter for handling attributes related to AdapterView.
- *
- * @author Akash Yadav
- */
-public abstract class AdapterViewAttrAdapter extends ViewGroupAttrAdapter {
-
- public AdapterViewAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof AdapterView;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- // No special attributes for AdapterView
- return super.apply(attribute, view);
- }
-
- protected ArrayAdapter newSimpleAdapter(Context ctx) {
- return newSimpleAdapter(ctx, newAdapterItems(4));
- }
-
- protected ArrayAdapter newSimpleAdapter(Context ctx, String[] items) {
- return new ArrayAdapter(ctx, android.R.layout.simple_list_item_1, items);
- }
-
- protected String[] newAdapterItems(int size) {
- final var items = new String[size];
- for (var i = 0; i < size; i++) {
- items[i] = "Item " + i;
- }
- return items;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ButtonAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ButtonAttrAdapter.java
deleted file mode 100644
index 484e7aafc..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ButtonAttrAdapter.java
+++ /dev/null
@@ -1,53 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Adapter for handling attributes related to Button.
- *
- * However, {@code android.widget.Button} has no special attributes. This adpater simply inherits
- * from {@link TextViewAttrAdapter}.
- *
- * @author Akash Yadav
- */
-public class ButtonAttrAdapter extends TextViewAttrAdapter {
-
- public ButtonAttrAdapter(@NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof Button;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- // No special attributes for Button
- return super.apply(attribute, view);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CheckBoxAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CheckBoxAttrAdapter.java
deleted file mode 100644
index fc59cb8fd..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CheckBoxAttrAdapter.java
+++ /dev/null
@@ -1,47 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.CheckBox;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/** Attribute handler for handling attributes related to CheckBox */
-public class CheckBoxAttrAdapter extends CompondButtonAttrAdapter {
-
- public CheckBoxAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof CheckBox;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
-
- // No special attributes for CheckBox
- return super.apply(attribute, view);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CheckedTextViewAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CheckedTextViewAttrAdapter.java
deleted file mode 100644
index 30acd6973..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CheckedTextViewAttrAdapter.java
+++ /dev/null
@@ -1,79 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.CheckedTextView;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute handler for handling attributes related to CheckedTextView.
- *
- * @author Akash Yadav
- */
-public class CheckedTextViewAttrAdapter extends TextViewAttrAdapter {
-
- public CheckedTextViewAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof CheckedTextView;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
-
- final CheckedTextView text = (CheckedTextView) view;
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "checkMarkTintMode":
- text.setCheckMarkTintMode(parsePorterDuffMode(value));
- break;
- case "checkMarkTint":
- text.setCheckMarkTintList(parseColorStateList(value, text.getContext()));
- break;
- case "checkMark":
- // Ignored...
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CompondButtonAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CompondButtonAttrAdapter.java
deleted file mode 100644
index 7dc02e551..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/CompondButtonAttrAdapter.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.itsaky.inflater.adapters.android.widget;
-
-import android.content.Context;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.CompoundButton;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute handler for handling attibutes to CompoundButton
- *
- * @author Akash Yadav
- */
-public class CompondButtonAttrAdapter extends ButtonAttrAdapter {
-
- public CompondButtonAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof CompoundButton;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final CompoundButton button = (CompoundButton) view;
- final Context context = button.getContext();
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "buttonTint":
- button.setButtonTintList(parseColorStateList(value, context));
- break;
- case "button":
- button.setButtonDrawable(parseDrawable(value, context));
- break;
- case "buttonTintMode":
- button.setButtonTintMode(parsePorterDuffMode(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/EditTextAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/EditTextAttrAdapter.java
deleted file mode 100644
index 029d170bb..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/EditTextAttrAdapter.java
+++ /dev/null
@@ -1,46 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.EditText;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-public class EditTextAttrAdapter extends TextViewAttrAdapter {
-
- public EditTextAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof EditText;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- // No special attributes for EditText
- return super.apply(attribute, view);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/FrameLayoutAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/FrameLayoutAttrAdapter.java
deleted file mode 100644
index 4d5180da3..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/FrameLayoutAttrAdapter.java
+++ /dev/null
@@ -1,75 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewGroupAttrAdapter;
-
-/**
- * Attribute adapter for {@link android.widget.FrameLayout}
- *
- * @author Akash Yadav
- */
-public class FrameLayoutAttrAdapter extends ViewGroupAttrAdapter {
-
- public FrameLayoutAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof FrameLayout;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
-
- final var frame = (FrameLayout) view;
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "foregroundGravity":
- frame.setForegroundGravity(parseGravity(value));
- break;
- case "measureAllChildren":
- frame.setMeasureAllChildren(parseBoolean(value));
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/GridLayoutAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/GridLayoutAttrAdapter.java
deleted file mode 100644
index e5319ce7f..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/GridLayoutAttrAdapter.java
+++ /dev/null
@@ -1,105 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.GridLayout;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewGroupAttrAdapter;
-
-/**
- * @author Akash Yadav
- */
-public class GridLayoutAttrAdapter extends ViewGroupAttrAdapter {
-
- public GridLayoutAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof GridLayout;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var grid = (GridLayout) view;
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "alignmentMode":
- grid.setAlignmentMode(parseAlignmentMode(value));
- break;
- case "columnCount":
- grid.setColumnCount(parseInteger(value, Integer.MIN_VALUE));
- break;
- case "columnOrderPreserved":
- grid.setColumnOrderPreserved(parseBoolean(value));
- break;
- case "orientation":
- grid.setOrientation(parseOrientation(value));
- break;
- case "rowCount":
- grid.setRowCount(parseInteger(value, Integer.MIN_VALUE));
- break;
- case "rowOrderPreserved":
- grid.setRowOrderPreserved(parseBoolean(value));
- break;
- case "useDefaultMargins":
- grid.setUseDefaultMargins(parseBoolean(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-
- protected int parseOrientation(String value) {
- if ("vertical".equals(value)) {
- return GridLayout.VERTICAL;
- }
-
- return GridLayout.HORIZONTAL;
- }
-
- protected int parseAlignmentMode(String value) {
- if ("alignBounds".equals(value)) {
- return GridLayout.ALIGN_BOUNDS;
- }
-
- return GridLayout.ALIGN_MARGINS;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ImageButtonAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ImageButtonAttrAdapter.java
deleted file mode 100644
index 6f3a0674f..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ImageButtonAttrAdapter.java
+++ /dev/null
@@ -1,50 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.ImageButton;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute handler for handling attributes related to ImageButton.
- *
- * @author Akash Yadav
- */
-public class ImageButtonAttrAdapter extends ImageViewAttrAdapter {
-
- public ImageButtonAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof ImageButton;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- // No special attributes for ImageButton
- return super.apply(attribute, view);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ImageViewAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ImageViewAttrAdapter.java
deleted file mode 100644
index 094058986..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ImageViewAttrAdapter.java
+++ /dev/null
@@ -1,135 +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.inflater.adapters.android.widget;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.ImageView;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewAttrAdapter;
-
-/**
- * Attribute handler for handling attributes related to ImageButton.
- *
- * @author Akash Yadav
- */
-public class ImageViewAttrAdapter extends ViewAttrAdapter {
-
- public ImageViewAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof ImageView;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final ImageView image = (ImageView) view;
- final Context context = image.getContext();
- final DisplayMetrics dm = context.getResources().getDisplayMetrics();
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "adjustViewBounds":
- image.setAdjustViewBounds(parseBoolean(value));
- break;
- case "baseline":
- image.setBaseline(parseDimension(value, 0, dm));
- break;
- case "baselineAlignBottom":
- image.setBaselineAlignBottom(parseBoolean(value));
- break;
- case "cropToPadding":
- image.setCropToPadding(parseBoolean(value));
- break;
- case "maxHeight":
- image.setMaxHeight(parseDimension(value, 0, dm));
- break;
- case "maxWidth":
- image.setMaxWidth(parseDimension(value, 0, dm));
- break;
- case "scaleType":
- image.setScaleType(parseScaleType(value));
- break;
- case "src":
- image.setImageDrawable(parseImageResource(value, context));
- break;
- case "tint":
- image.setImageTintList(parseColorStateList(value, context));
- break;
- case "tintMode":
- image.setImageTintMode(parsePorterDuffMode(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-
- private Drawable parseImageResource(String value, Context context) {
- if (value.startsWith("@drawable/") || value.startsWith("@mipmap/")) {
- return parseDrawable(value, context);
- }
- return ContextCompat.getDrawable(context, android.R.drawable.ic_delete);
- }
-
- private ImageView.ScaleType parseScaleType(String value) {
- switch (value) {
- case "center":
- return ImageView.ScaleType.CENTER;
- case "centerCrop":
- return ImageView.ScaleType.CENTER_CROP;
- case "centerInside":
- return ImageView.ScaleType.CENTER_INSIDE;
- case "fitEnd":
- return ImageView.ScaleType.FIT_END;
- case "fitStart":
- return ImageView.ScaleType.FIT_START;
- case "fitXY":
- return ImageView.ScaleType.FIT_XY;
- case "matrix":
- return ImageView.ScaleType.MATRIX;
- case "fitCenter":
- default:
- return ImageView.ScaleType.FIT_CENTER;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/LinearLayoutAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/LinearLayoutAttrAdapter.java
deleted file mode 100644
index 169e31e78..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/LinearLayoutAttrAdapter.java
+++ /dev/null
@@ -1,98 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewGroupAttrAdapter;
-
-/**
- * Adapter for handling attributes related to LinearLayout.
- *
- * @author Akash Yadav
- */
-public class LinearLayoutAttrAdapter extends ViewGroupAttrAdapter {
-
- public LinearLayoutAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof LinearLayout;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final LinearLayout linear = (LinearLayout) view;
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "baselineAligned":
- linear.setBaselineAligned(parseBoolean(value));
- break;
- case "baselineAlignedChildIndex":
- linear.setBaselineAlignedChildIndex(parseInteger(value, linear.getChildCount()));
- break;
- case "gravity":
- linear.setGravity(parseGravity(value));
- break;
- case "measureWithLargestChild":
- linear.setMeasureWithLargestChildEnabled(parseBoolean(value));
- break;
- case "orientation":
- linear.setOrientation(parseOrientation(value));
- break;
- case "weightSum":
- linear.setWeightSum(parseFloat(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-
- protected int parseOrientation(@NonNull String value) {
- switch (value) {
- case "vertical":
- return LinearLayout.VERTICAL;
- case "horizontal":
- default:
- return LinearLayout.HORIZONTAL;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ListViewAttrAdapter.kt b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ListViewAttrAdapter.kt
deleted file mode 100644
index bab935898..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ListViewAttrAdapter.kt
+++ /dev/null
@@ -1,65 +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.inflater.adapters.android.widget
-
-import android.util.DisplayMetrics
-import android.view.View
-import android.widget.ArrayAdapter
-import android.widget.ListView
-import com.blankj.utilcode.util.SizeUtils
-import com.itsaky.inflater.IAttribute
-import com.itsaky.inflater.IResourceTable
-
-/** @author Akash Yadav */
-class ListViewAttrAdapter(resourceTable: IResourceTable, displayMetrics: DisplayMetrics) :
- AbsListViewAttrAdapter(resourceTable, displayMetrics) {
-
- override fun isApplicableTo(view: View?): Boolean {
- return view is ListView
- }
-
- override fun apply(attribute: IAttribute, view: View): Boolean {
- val list = view as ListView
- val value = attribute.value
- val context = list.context
-
- if (!canHandleNamespace(attribute)) {
- return false
- }
-
- var handled = true
-
- when (attribute.attributeName) {
- "divider" -> list.divider = parseDrawable(value, context)
- "dividerHeight" ->
- list.dividerHeight = parseDimension(value, SizeUtils.dp2px(1f), displayMetrics)
- "entries" -> {
- val entries = parseArray(value)
- list.adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, entries)
- }
- "footerDividersEnabled" -> list.setFooterDividersEnabled(parseBoolean(value))
- "headerDividersEnabled" -> list.setHeaderDividersEnabled(parseBoolean(value))
- }
-
- if (!handled) {
- handled = super.apply(attribute, view)
- }
-
- return handled
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ProgressBarAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ProgressBarAttrAdapter.java
deleted file mode 100644
index 77cadccb9..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ProgressBarAttrAdapter.java
+++ /dev/null
@@ -1,139 +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.inflater.adapters.android.widget;
-
-import android.content.Context;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.ProgressBar;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewAttrAdapter;
-
-/**
- * Attribute adapter for handling attributes related to ProgressBar.
- *
- * @author Akash Yadav
- */
-public class ProgressBarAttrAdapter extends ViewAttrAdapter {
-
- public ProgressBarAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof ProgressBar;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final ProgressBar pb = (ProgressBar) view;
- final Context context = pb.getContext();
- final DisplayMetrics dm = context.getResources().getDisplayMetrics();
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "indeterminate":
- pb.setIndeterminate(parseBoolean(value));
- break;
- case "indeterminateDrawable":
- pb.setIndeterminateDrawable(parseDrawable(value, context));
- break;
- case "indeterminateTint":
- pb.setIndeterminateTintList(parseColorStateList(value, context));
- break;
- case "indeterminateTintMode":
- pb.setIndeterminateTintMode(parsePorterDuffMode(value));
- break;
- case "max":
- pb.setMax(parseInteger(value, 100));
- break;
- case "maxHeight":
- if (isApi29()) {
- pb.setMaxHeight(parseDimension(value, Integer.MAX_VALUE, dm));
- }
- break;
- case "maxWidth":
- if (isApi29()) {
- pb.setMaxWidth(parseDimension(value, Integer.MAX_VALUE, dm));
- }
- break;
- case "min":
- pb.setMin(parseInteger(value, 0));
- break;
- case "minHeight":
- if (isApi29()) {
- pb.setMinHeight(parseDimension(value, 0, dm));
- }
- break;
- case "minWidth":
- if (isApi29()) {
- pb.setMinWidth(parseDimension(value, 0, dm));
- }
- break;
- case "progress":
- pb.setProgress(parseInteger(value, 50));
- break;
- case "progressBackgroundTint":
- pb.setProgressBackgroundTintList(parseColorStateList(value, context));
- break;
- case "progressBackgroundTintMode":
- pb.setProgressBackgroundTintMode(parsePorterDuffMode(value));
- break;
- case "progressDrawable":
- pb.setProgressDrawable(parseDrawable(value, context));
- break;
- case "progressTint":
- pb.setProgressTintList(parseColorStateList(value, context));
- break;
- case "progressTintMode":
- pb.setProgressTintMode(parsePorterDuffMode(value));
- break;
- case "secondaryProgress":
- pb.setSecondaryProgress(parseInteger(value, 0));
- break;
- case "secondaryProgressTint":
- pb.setSecondaryProgressTintList(parseColorStateList(value, context));
- break;
- case "secondaryProgressTintMode":
- pb.setSecondaryProgressTintMode(parsePorterDuffMode(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/RadioButtonAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/RadioButtonAttrAdapter.java
deleted file mode 100644
index fdcafca02..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/RadioButtonAttrAdapter.java
+++ /dev/null
@@ -1,51 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.RadioButton;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute adapter for handling attributes related to RadioButton.
- *
- * @author Akash Yadav
- */
-public class RadioButtonAttrAdapter extends CompondButtonAttrAdapter {
-
- public RadioButtonAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof RadioButton;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- // No special attributes for RadioButton
- return super.apply(attribute, view);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/RelativeLayoutAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/RelativeLayoutAttrAdapter.java
deleted file mode 100644
index c26ed3523..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/RelativeLayoutAttrAdapter.java
+++ /dev/null
@@ -1,77 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.RelativeLayout;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewGroupAttrAdapter;
-
-/**
- * Attribute adapter for handling attributes related to RelativeLayout.
- *
- * @author Akash Yadav
- */
-public class RelativeLayoutAttrAdapter extends ViewGroupAttrAdapter {
-
- public RelativeLayoutAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof RelativeLayout;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
-
- final RelativeLayout relative = (RelativeLayout) view;
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "gravity":
- relative.setGravity(parseGravity(value));
- break;
- case "ignoreGravity":
- relative.setIgnoreGravity(parseId(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SeekBarAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SeekBarAttrAdapter.java
deleted file mode 100644
index 3390dd649..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SeekBarAttrAdapter.java
+++ /dev/null
@@ -1,69 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.SeekBar;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute adapter for handling attributes related to SeekBar.
- *
- * @author Akash Yadav
- */
-public class SeekBarAttrAdapter extends AbsSeekBarAttrAdapter {
-
- public SeekBarAttrAdapter(@NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof SeekBar;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var seek = (SeekBar) view;
- final var context = seek.getContext();
- final var namespace = attribute.getNamespace();
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(namespace)) {
- return false;
- }
- boolean handled = true;
-
- switch (name) {
- case "thumb":
- seek.setThumb(parseDrawable(value, context));
- break;
- default:
- handled = false;
- break;
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SpinnerAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SpinnerAttrAdapter.java
deleted file mode 100644
index bbb21a555..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SpinnerAttrAdapter.java
+++ /dev/null
@@ -1,87 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.Spinner;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute adapter for handling attributes related to Spinner.
- *
- * @author Akash Yadav
- */
-public class SpinnerAttrAdapter extends AbsSpinnerAttrAdapter {
-
- public SpinnerAttrAdapter(@NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof Spinner;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var spinner = (Spinner) view;
- final var context = spinner.getContext();
- final var dm = context.getResources().getDisplayMetrics();
- final var namespace = attribute.getNamespace();
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(namespace)) {
- return false;
- }
-
- boolean handled = true;
-
- switch (name) {
- case "dropDownHorizontalOffset":
- spinner.setDropDownHorizontalOffset(parseDimension(value, 0, dm));
- break;
- case "dropDownVerticalOffset":
- spinner.setDropDownVerticalOffset(parseDimension(value, 0, dm));
- break;
- case "dropDownWidth":
- spinner.setDropDownWidth(parseDimension(value, 0, dm));
- break;
- case "gravity":
- spinner.setGravity(parseGravity(value));
- break;
- case "popupBackground":
- spinner.setPopupBackgroundDrawable(parseDrawable(value, context));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SwitchAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SwitchAttrAdapter.java
deleted file mode 100644
index 0dea4765a..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/SwitchAttrAdapter.java
+++ /dev/null
@@ -1,116 +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.inflater.adapters.android.widget;
-
-import android.annotation.SuppressLint;
-import android.graphics.Typeface;
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.Switch;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute adapter for {@link Switch}.
- *
- * @author Akash Yadav
- */
-public class SwitchAttrAdapter extends CompondButtonAttrAdapter {
-
- public SwitchAttrAdapter(@NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof Switch;
- }
-
- @SuppressLint("UseSwitchCompatOrMaterialCode")
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var button = (Switch) view;
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "showText":
- button.setShowText(parseBoolean(value));
- break;
- case "splitTrack":
- button.setSplitTrack(parseBoolean(value));
- break;
- case "switchMinWidth":
- button.setSwitchMinWidth(parseDimension(value, 0));
- break;
- case "switchPadding":
- button.setSwitchPadding(parseDimension(value, 0));
- break;
- case "textOff":
- button.setTextOff(parseString(value));
- break;
- case "textOn":
- button.setTextOn(parseString(value));
- break;
- case "textStyle":
- button.setSwitchTypeface(Typeface.DEFAULT, parseTextStyle(value));
- break;
- case "thumb":
- button.setThumbDrawable(parseDrawable(value, button.getContext()));
- break;
- case "thumbTextPadding":
- button.setThumbTextPadding(parseDimension(value, 0));
- break;
- case "thumbTint":
- button.setThumbTintList(parseColorStateList(value, button.getContext()));
- break;
- case "thumbTintMode":
- button.setThumbTintMode(parsePorterDuffMode(value));
- break;
- case "track":
- button.setTrackDrawable(parseDrawable(value, button.getContext()));
- break;
- case "trackTint":
- button.setTrackTintList(parseColorStateList(value, button.getContext()));
- break;
- case "trackTintMode":
- button.setTrackTintMode(parsePorterDuffMode(value));
- break;
- case "typeface":
- button.setSwitchTypeface(parseTypeface(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/TextViewAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/TextViewAttrAdapter.java
deleted file mode 100644
index f6520b6ad..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/TextViewAttrAdapter.java
+++ /dev/null
@@ -1,251 +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.inflater.adapters.android.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.text.util.Linkify;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-
-import com.blankj.utilcode.util.SizeUtils;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.adapters.android.view.ViewAttrAdapter;
-
-import java.util.regex.Pattern;
-
-/**
- * Adapter for handling attributes related to TextView.
- *
- * @author Akash Yadav
- */
-public class TextViewAttrAdapter extends ViewAttrAdapter {
-
- public TextViewAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof TextView;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final TextView text = (TextView) view;
- final String name = attribute.getAttributeName();
- final String value = attribute.getValue();
- final Resources res = view.getResources();
- final DisplayMetrics dm = res.getDisplayMetrics();
- final Context ctx = view.getContext();
- final Drawable[] drawables = text.getCompoundDrawables();
- final Drawable[] drawablesRelative = text.getCompoundDrawablesRelative();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "autoLink":
- text.setAutoLinkMask(parseAutoLinkMask(value));
- break;
- case "drawableLeft":
- text.setCompoundDrawables(
- parseDrawable(value, ctx), drawables[1], drawables[2], drawables[3]);
- break;
- case "drawableTop":
- text.setCompoundDrawables(
- drawables[0], parseDrawable(value, ctx), drawables[2], drawables[3]);
- break;
- case "drawableRight":
- text.setCompoundDrawables(
- drawables[0], drawables[1], parseDrawable(value, ctx), drawables[3]);
- break;
- case "drawableBottom":
- text.setCompoundDrawables(
- drawables[0], drawables[1], drawables[2], parseDrawable(value, ctx));
- break;
- case "drawableStart":
- text.setCompoundDrawables(
- parseDrawable(value, ctx),
- drawablesRelative[1],
- drawablesRelative[2],
- drawablesRelative[3]);
- break;
- case "drawableEnd":
- text.setCompoundDrawables(
- drawablesRelative[0],
- drawablesRelative[1],
- parseDrawable(value, ctx),
- drawablesRelative[3]);
- break;
- case "drawablePadding":
- text.setCompoundDrawablePadding(parseDimension(value, 0, dm));
- break;
- case "ellipsize":
- text.setEllipsize(parseEllipsize(value));
- break;
- case "gravity":
- text.setGravity(parseGravity(value));
- break;
- case "hint":
- text.setHint(parseString(value));
- break;
- case "letterSpacing":
- text.setLetterSpacing(parseFloat(value));
- break;
- case "lineHeight":
- text.setLines(parseInteger(value, Integer.MAX_VALUE));
- break;
- case "linksClickable":
- text.setLinksClickable(parseBoolean(value));
- break;
- case "marqueeRepeatLimit":
- text.setMarqueeRepeatLimit(parseInteger(value, Integer.MAX_VALUE));
- break;
- case "maxLines":
- text.setMaxLines(parseInteger(value, Integer.MAX_VALUE));
- break;
- case "minLines":
- text.setMinLines(parseInteger(value, 1));
- break;
- case "singleLine":
- text.setSingleLine(parseBoolean(value));
- break;
- case "text":
- text.setText(parseString(value));
- break;
- case "textAllCaps":
- text.setAllCaps(parseBoolean(value));
- break;
- case "textColor":
- text.setTextColor(parseColor(value, ctx));
- break;
- case "textColorHint":
- text.setHintTextColor(parseColor(value, ctx));
- break;
- case "textSize":
- text.setTextSize(
- TypedValue.COMPLEX_UNIT_PX, parseDimension(value, SizeUtils.sp2px(14), dm));
- break;
- case "textStyle":
- text.setTypeface(text.getTypeface(), parseTextStyle(value));
- break;
- case "typeface":
- text.setTypeface(parseTypeface(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-
- protected int parseTextStyle(@NonNull String value) {
- final String[] splits = value.split(Pattern.quote("|"));
- int mask = 0;
- for (String split : splits) {
- mask |= textStyleFor(split);
- }
- return mask;
- }
-
- protected int textStyleFor(@NonNull String split) {
- switch (split) {
- case "bold":
- return Typeface.BOLD;
- case "italic":
- return Typeface.ITALIC;
- case "normal":
- default:
- return Typeface.NORMAL;
- }
- }
-
- protected Typeface parseTypeface(@NonNull String value) {
- switch (value) {
- case "sans":
- return Typeface.SANS_SERIF;
- case "serif":
- return Typeface.SERIF;
- case "monospace":
- return Typeface.MONOSPACE;
- case "normal":
- default:
- return Typeface.DEFAULT;
- }
- }
-
- protected TextUtils.TruncateAt parseEllipsize(@NonNull String value) {
- switch (value) {
- case "end":
- return TextUtils.TruncateAt.END;
- case "start":
- return TextUtils.TruncateAt.START;
- case "marquee":
- return TextUtils.TruncateAt.MARQUEE;
- case "middle":
- return TextUtils.TruncateAt.MIDDLE;
- case "none":
- default:
- return null;
- }
- }
-
- protected int parseAutoLinkMask(@NonNull String value) {
- final String[] splits = value.split(Pattern.quote("|"));
- int mask = 0;
- for (String split : splits) {
- mask |= autoLinkMaskFor(split);
- }
- return mask;
- }
-
- protected int autoLinkMaskFor(@NonNull String mask) {
- switch (mask) {
- case "all":
- return Linkify.ALL;
- case "web":
- return Linkify.WEB_URLS;
- case "phone":
- return Linkify.PHONE_NUMBERS;
- case "map":
- return Linkify.MAP_ADDRESSES;
- case "email":
- return Linkify.EMAIL_ADDRESSES;
- case "none":
- default:
- return 0;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ToggleButtonAttrAdapter.java b/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ToggleButtonAttrAdapter.java
deleted file mode 100644
index 65c21a361..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/adapters/android/widget/ToggleButtonAttrAdapter.java
+++ /dev/null
@@ -1,79 +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.inflater.adapters.android.widget;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.ToggleButton;
-
-import androidx.annotation.NonNull;
-
-import com.blankj.utilcode.util.ReflectUtils;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IResourceTable;
-
-/**
- * Attribute adapter for {@link ToggleButton}.
- *
- * @author Akash Yadav
- */
-public class ToggleButtonAttrAdapter extends CompondButtonAttrAdapter {
-
- public ToggleButtonAttrAdapter(
- @NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- super(resourceFinder, displayMetrics);
- }
-
- @Override
- public boolean isApplicableTo(View view) {
- return view instanceof ToggleButton;
- }
-
- @Override
- public boolean apply(@NonNull IAttribute attribute, @NonNull View view) {
- final var button = (ToggleButton) view;
- final var name = attribute.getAttributeName();
- final var value = attribute.getValue();
-
- if (!canHandleNamespace(attribute)) {
- return false;
- }
-
- boolean handled = true;
- switch (name) {
- case "disabledAlpha":
- ReflectUtils.reflect(button).field("mDisabledAlpha", parseFloat(value, 0.5f));
- break;
- case "textOff":
- button.setTextOff(parseString(value));
- break;
- case "textOn":
- button.setTextOn(parseString(value));
- break;
- default:
- handled = false;
- break;
- }
-
- if (!handled) {
- handled = super.apply(attribute, view);
- }
-
- return handled;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/BitmapDrawableParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/BitmapDrawableParser.java
deleted file mode 100644
index 79ddd4985..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/BitmapDrawableParser.java
+++ /dev/null
@@ -1,152 +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.inflater.drawable;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Shader;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.InflateException;
-
-import org.jetbrains.annotations.Contract;
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- * Parser for parsing <bitmap> drawables.
- *
- * @author Akash Yadav
- */
-public class BitmapDrawableParser extends IDrawableParser {
-
- protected BitmapDrawableParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Override
- public Drawable parseDrawable() throws Exception {
- var index = attrIndex("src");
- if (index == -1) {
- throw new InflateException("Invalid drawable. No android:src specified!");
- }
-
- var val = value(index);
- var dr = parseDrawable(val, BaseApplication.getBaseInstance());
- if (dr == null) {
- throw new InflateException("Cannot parse drawable for android:src = " + val);
- }
-
- final var bitmap =
- new BitmapDrawable(BaseApplication.getBaseInstance().getResources(), toBitmap(dr));
-
- index = attrIndex("antialias");
- if (index != -1) {
- bitmap.setAntiAlias(parseBoolean(value(index)));
- }
-
- index = attrIndex("dither");
- if (index != -1) {
- bitmap.setDither(parseBoolean(value(index)));
- }
-
- index = attrIndex("filter");
- if (index != -1) {
- bitmap.setFilterBitmap(parseBoolean(value(index)));
- }
-
- index = attrIndex("gravity");
- if (index != -1) {
- bitmap.setGravity(parseGravity(value(index)));
- }
-
- index = attrIndex("mipMap");
- if (index != -1) {
- bitmap.setMipMap(parseBoolean(value(index)));
- }
-
- index = attrIndex("tileMode");
- if (index != -1) {
- var mode = parseTileMode(value(index));
- bitmap.setTileModeXY(mode, mode);
- }
-
- index = attrIndex("tileModeX");
- if (index != -1) {
- var mode = parseTileMode(value(index));
- bitmap.setTileModeX(mode);
- }
-
- index = attrIndex("tileModeY");
- if (index != -1) {
- var mode = parseTileMode(value(index));
- bitmap.setTileModeY(mode);
- }
-
- return bitmap;
- }
-
- @Nullable
- @Contract(pure = true)
- private Shader.TileMode parseTileMode(@NonNull String value) {
- switch (value) {
- case "clamp":
- return Shader.TileMode.CLAMP;
- case "mirror":
- return Shader.TileMode.MIRROR;
- case "repeat":
- return Shader.TileMode.REPEAT;
- case "disabled":
- default:
- return null; // null = disabled
- }
- }
-
- private Bitmap toBitmap(@NonNull Drawable dr) {
- if (dr instanceof BitmapDrawable) {
- var bit = (BitmapDrawable) dr;
- if (bit.getBitmap() != null) {
- return bit.getBitmap();
- }
- }
-
- Bitmap bit;
- if (dr.getIntrinsicWidth() > 0 && dr.getIntrinsicHeight() > 0) {
- bit =
- Bitmap.createBitmap(
- dr.getIntrinsicWidth(), dr.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
- } else {
- bit = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
- }
-
- final var canvas = new Canvas(bit);
- dr.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- dr.draw(canvas);
- return bit;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ClipDrawableParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ClipDrawableParser.java
deleted file mode 100644
index 97e6ac26a..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ClipDrawableParser.java
+++ /dev/null
@@ -1,88 +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.inflater.drawable;
-
-import android.graphics.drawable.ClipDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.InflateException;
-import com.itsaky.inflater.util.Preconditions;
-
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- * Parser for parsing <clip> drawables;
- *
- * @author Akash Yadav
- */
-public class ClipDrawableParser extends IDrawableParser {
-
- protected ClipDrawableParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Override
- public Drawable parseDrawable() throws Exception {
- var index = attrIndex("drawable");
- if (index == -1) {
- throw new InflateException(" drawable must specify android:drawable attribute");
- }
-
- var val = value(index);
- Preconditions.assertNotBlank(val, "Invalid value specified to android:drawable attribute");
-
- final var drawable = parseDrawable(val, BaseApplication.getBaseInstance());
- if (drawable == null) {
- throw new InflateException("Unable to parse drawable for value: " + val);
- }
-
- var orientation = ClipDrawable.HORIZONTAL;
- index = attrIndex("clipOrientation");
- if (index != -1) {
- orientation = parseClipOrientation(value(index));
- }
-
- var gravity = Gravity.LEFT;
- index = attrIndex("gravity");
- if (index != -1) {
- gravity = parseGravity(value(index));
- }
-
- return new ClipDrawable(drawable, gravity, orientation);
- }
-
- protected int parseClipOrientation(@NonNull final String value) {
- switch (value) {
- case "vertical":
- return ClipDrawable.VERTICAL;
- default:
- case "horizontal":
- return ClipDrawable.HORIZONTAL;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/DrawableParserFactory.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/DrawableParserFactory.java
deleted file mode 100644
index 75e9c68ee..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/DrawableParserFactory.java
+++ /dev/null
@@ -1,208 +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.inflater.drawable;
-
-import android.content.Context;
-import android.graphics.NinePatch;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.blankj.utilcode.util.FileIOUtils;
-import com.blankj.utilcode.util.ImageUtils;
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IResourceTable;
-import com.sdsmdg.harjot.vectormaster.VectorMasterDrawable;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-
-/**
- * Utility methods for creating instances of suitable drawable parsers for a file or an XML code.
- *
- * @author Akash Yadav
- */
-public abstract class DrawableParserFactory {
-
- private static final ILogger LOG = ILogger.newInstance("IDrawableParser");
-
- /**
- * Create a new drawable parser for the given file. If the given file is not an XML Document, then
- * a no-op parser is returned which simply returns the drawable for that file. If the file is an
- * XML document, then a suitable parser is determined by looking at the root tag of the drawable.
- *
- * @param context The context. This will be used for obtaining app resources.
- * @param file The file to parse.
- * @param resourceFinder The resource finder. Used for finding references to another resources.
- * @return A new {@link IDrawableParser} instance if the inputs are valid, or {@code null} if
- * there were any issues creating the parser.
- * @throws XmlPullParserException Thrown by the {@link XmlPullParser#setInput(Reader)}.
- * @throws IOException Thrown by {@link XmlPullParser#next()}
- */
- @Nullable
- public static IDrawableParser newParser(
- @NonNull final Context context, @NonNull final File file, final IResourceTable resourceFinder)
- throws XmlPullParserException, IOException {
- if (file.getName().endsWith(".xml")) {
- final var code = FileIOUtils.readFile2String(file);
- return DrawableParserFactory.newXmlDrawableParser(
- code, resourceFinder, context.getResources().getDisplayMetrics());
- } else {
- final var bitmap = ImageUtils.getBitmap(file);
- if (bitmap == null) {
- return null;
- }
-
- final var chunk = bitmap.getNinePatchChunk();
- if (NinePatch.isNinePatchChunk(chunk)) {
- return new NoParser(
- new NinePatchDrawable(context.getResources(), new NinePatch(bitmap, chunk)));
- }
-
- return new NoParser(new BitmapDrawable(context.getResources(), bitmap));
- }
- }
-
- /**
- * Create a new drawable parser for the given xml code.
- *
- * @param xmlDrawable The XML code. This must be valid.
- * @param resourceFinder The resource finder. Used for finding references to another resources.
- * @param displayMetrics This will be used by generated parsers to parse dimension vlaues.
- * @return A new {@link IDrawableParser} instance if the inputs are valid, or {@code null} if
- * there were any issues creating the parser.
- * @throws XmlPullParserException Thrown by the {@link XmlPullParser#setInput(Reader)}.
- * @throws IOException Thrown by {@link XmlPullParser#next()}
- */
- @Nullable
- public static IDrawableParser newXmlDrawableParser(
- String xmlDrawable, IResourceTable resourceFinder, DisplayMetrics displayMetrics)
- throws XmlPullParserException, IOException {
- final var factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
-
- final var parser = factory.newPullParser();
- parser.setInput(new StringReader(xmlDrawable));
-
- var event = parser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final var name = parser.getName();
- return parserForTag(xmlDrawable, resourceFinder, displayMetrics, parser, name);
- }
- event = parser.next();
- }
-
- // TODO Implement parsers for these root tags if possible
- // 1. ---------- DONE
- // 2. ------ DONE
- // 3. ------ DONE
- // 4.
- // 5.
- // 6.
- // 7. ----------- DONE
- // 8. ------------ DONE
- // 9. ----------- DONE
- // Cannot parse this type of drawable
- return null;
- }
-
- @Nullable
- public static IDrawableParser parserForTag(
- String xmlDrawable,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- XmlPullParser parser,
- @NonNull String name)
- throws XmlPullParserException {
- Class extends IDrawableParser> impl = null;
- switch (name) {
- case "shape":
- impl = ShapeDrawableParser.class;
- break;
- case "inset":
- impl = InsetDrawableParser.class;
- break;
- case "layer-list":
- impl = LayerListParser.class;
- break;
- case "bitmap":
- impl = BitmapDrawableParser.class;
- break;
- case "scale":
- impl = ScaleDrawableParser.class;
- break;
- case "clip":
- impl = ClipDrawableParser.class;
- break;
- case "selector":
- impl = StateListParser.class;
- break;
- case "vector":
- if (xmlDrawable != null) {
- return new NoParser(VectorMasterDrawable.fromXML(xmlDrawable));
- }
- return null;
- }
-
- try {
- if (impl != null) {
- final var constructor =
- impl.getDeclaredConstructor(
- XmlPullParser.class, IResourceTable.class, DisplayMetrics.class, int.class);
- return constructor.newInstance(
- parser, resourceFinder, displayMetrics, IDrawableParser.ANY_DEPTH);
- }
- } catch (Throwable th) {
- LOG.error("No drawable parser found for tag", name, th);
- }
-
- return null;
- }
-
- /** Instead of parsing anything, this returns the provided drawable. */
- private static class NoParser extends IDrawableParser {
-
- private final Drawable parsed;
-
- protected NoParser(final Drawable parsed) {
- super(null, null, null, ANY_DEPTH);
- this.parsed = parsed;
- }
-
- @Override
- public Drawable parse() throws Exception {
- return parsed;
- }
-
- @Override
- public Drawable parseDrawable() {
- return parsed;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/IDrawableParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/IDrawableParser.java
deleted file mode 100644
index 4ceb96386..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/IDrawableParser.java
+++ /dev/null
@@ -1,162 +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.inflater.drawable;
-
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.ChecksSdkIntAtLeast;
-
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.util.CommonParseUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- * Base class for drawable parsers.
- *
- * @author Akash Yadav
- */
-public abstract class IDrawableParser extends CommonParseUtils {
-
- public static final int ANY_DEPTH = -1;
-
- protected final XmlPullParser parser;
- protected int minDepth;
-
- protected IDrawableParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(resourceFinder, displayMetrics);
- this.parser = parser;
- this.minDepth = minDepth;
- }
-
- /**
- * Parse the drawable using the already provided parser and data.
- *
- * @return The parsed {@link Drawable} or null if the parse was unsuccessful.
- * @throws Exception If any fatal error occurred while parsing the drawable.
- */
- public Drawable parse() throws Exception {
- var index = attrIndex("visible");
- var visible = true;
- if (index != -1) {
- visible = parseBoolean(value(index));
- }
-
- var autoMirrored = false;
- index = attrIndex("autoMirrored");
- if (index != -1) {
- autoMirrored = parseBoolean(value(index));
- }
-
- var level = 0;
- index = attrIndex("level");
- if (index != -1) {
- level = parseInteger(value(index), 0);
- }
-
- final var drawable = parseDrawable();
-
- if (drawable != null) {
- drawable.setVisible(visible, false);
- drawable.setAutoMirrored(autoMirrored);
- drawable.setLevel(level);
- }
-
- return drawable;
- }
-
- /**
- * Actual implementation of the parse logic.
- *
- * @return The parsed drawable. Maybe null.
- * @throws Exception If any fatal error occurs while parsing the drawable.
- */
- protected abstract Drawable parseDrawable() throws Exception;
-
- /**
- * Find the index of the attribute with the given name.
- *
- * @param name The name of the attribute to look for.
- * @return The index of the attribute or -1.
- */
- protected int attrIndex(final String name) {
- for (int i = 0; i < this.parser.getAttributeCount(); i++) {
- if (this.parser.getAttributeName(i).equals(name)) {
- return i;
- }
- }
-
- return -1;
- }
-
- /**
- * Get the value of the attribute at the given index.
- *
- * @param index The index of the attribute.
- * @return The value of the attribute.
- */
- protected String value(int index) {
- return parser.getAttributeValue(index);
- }
-
- /**
- * Set the minimum depth that this parser should keep parsing. Subclasses are expected to parse
- * child tags with depths greater than this specified value.
- *
- * @param minDepth The minimum depth of this parser.
- */
- public void setMinDepth(int minDepth) {
- this.minDepth = minDepth;
- }
-
- /**
- * Checks if the drawable parser is allowed to parse at the current depth. This must be checked if
- * the drawable parser keeps looking for {@link XmlPullParser#START_TAG} or {@link
- * XmlPullParser#END_TAG}.
- *
- * The {@link LayerListParser} can contain tags which are expected to be parsed by other
- * parsers. So, if the nesting parser does not check if this method if true, it might
- * consume all the events and the {@link LayerListParser} will have invalid data to parse. In some
- * cases, the nested parser might consume all the events until {@link XmlPullParser#END_DOCUMENT}.
- *
- * @return true if the parser can keep parsing, false otherwise.
- */
- protected boolean canParse() {
- return this.parser.getDepth() >= minDepth;
- }
-
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.P)
- protected boolean isApi28() {
- return Build.VERSION.SDK_INT >= 28;
- }
-
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.Q)
- protected boolean isApi29() {
- return Build.VERSION.SDK_INT >= 29;
- }
-
- @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.R)
- protected boolean isApi30() {
- return Build.VERSION.SDK_INT >= 30;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/InsetDrawableParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/InsetDrawableParser.java
deleted file mode 100644
index 81872f702..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/InsetDrawableParser.java
+++ /dev/null
@@ -1,76 +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.inflater.drawable;
-
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.InsetDrawable;
-import android.util.DisplayMetrics;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.InflateException;
-import com.itsaky.inflater.util.Preconditions;
-
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- * Parser for <inset> drawables.
- *
- * @author Akash Yadav
- */
-public class InsetDrawableParser extends IDrawableParser {
-
- protected InsetDrawableParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Override
- public Drawable parseDrawable() throws Exception {
- var index = attrIndex("drawable");
- if (index == -1) {
- throw new InflateException("No drawable specified for drawable");
- }
-
- var value = value(index);
- Preconditions.assertNotBlank(value, "Invalid value specified for android:drawable");
-
- final var drawable = parseDrawable(value, BaseApplication.getBaseInstance());
- if (drawable == null) {
- throw new InflateException(
- "Unable to parse inset drawable. Failed to parse android:drawable");
- }
-
- index = attrIndex("insetLeft");
- final var left = index == -1 ? 0 : parseDimension(value(index), 0);
-
- index = attrIndex("insetTop");
- final var top = index == -1 ? 0 : parseDimension(value(index), 0);
-
- index = attrIndex("insetRight");
- final var right = index == -1 ? 0 : parseDimension(value(index), 0);
-
- index = attrIndex("insetBottom");
- final var bottom = index == -1 ? 0 : parseDimension(value(index), 0);
-
- return new InsetDrawable(drawable, left, top, right, bottom);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/LayerListParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/LayerListParser.java
deleted file mode 100644
index bba53a68c..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/LayerListParser.java
+++ /dev/null
@@ -1,141 +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.inflater.drawable;
-
-import static com.itsaky.inflater.util.Preconditions.assertNotBlank;
-
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.util.TextDrawable;
-
-import org.jetbrains.annotations.Contract;
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- * Parser for parsing <layer-list> drawables.
- *
- * @author Akash Yadav
- */
-public class LayerListParser extends IDrawableParser {
-
- protected LayerListParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Override
- public Drawable parseDrawable() throws Exception {
- final var layer = new LayerDrawable(new Drawable[0]);
- var index = -1;
- var value = "";
- var event = parser.getEventType();
- int left = 0, top = 0, right = 0, bottom = 0;
- var parseInner = true;
- while (event != XmlPullParser.END_DOCUMENT && canParse()) {
- if (event == XmlPullParser.START_TAG) {
- final var name = parser.getName();
- if ("item".equals(name)) {
- index = attrIndex("drawable");
- Drawable drawable = null;
- if (index != -1) {
- value = value(index);
- assertNotBlank(value, "Invalid value for android:drawable attribute");
- drawable = parseDrawable(value, BaseApplication.getBaseInstance());
-
- // if the android:drawable is specified, we do not parse the inner elements
- // of -
- parseInner = false;
- }
-
- index = attrIndex("left");
- left = index == -1 ? 0 : parseDimension(value(index), 0);
-
- index = attrIndex("top");
- top = index == -1 ? 0 : parseDimension(value(index), 0);
-
- index = attrIndex("right");
- right = index == -1 ? 0 : parseDimension(value(index), 0);
-
- index = attrIndex("bottom");
- bottom = index == -1 ? 0 : parseDimension(value(index), 0);
-
- if (drawable == null) {
- parseInner = true;
- } else {
- addToLayer(layer, drawable, left, top, right, bottom);
- }
-
- if (!parseInner) {
- skipToEndTag(this.parser.getDepth());
- }
- } else if (parser.getDepth() > 2 && parseInner) {
- // depth 1 =
- // depth 2 =
-
- // depth > 2 = child drawables inside
- tag
- final var parser =
- DrawableParserFactory.parserForTag(
- null, resourceFinder, displayMetrics, this.parser, name);
- if (parser != null) {
- parser.setMinDepth(this.parser.getDepth());
- var d = parser.parse();
- if (d == null) {
- d = unsupported();
- }
-
- addToLayer(layer, d, left, top, right, bottom);
- } else {
- addToLayer(layer, unsupported(), left, top, right, bottom);
- }
- }
- }
- event = parser.next();
- }
-
- return layer;
- }
-
- private void addToLayer(
- @NonNull LayerDrawable layer, Drawable drawable, int left, int top, int right, int bottom) {
- final int index = layer.addLayer(drawable);
- layer.setLayerInset(index, left, top, right, bottom);
- }
-
- private void skipToEndTag(int depth) throws Exception {
- for (var event = parser.getEventType();
- event != XmlPullParser.END_DOCUMENT;
- event = parser.next()) {
- if (event == XmlPullParser.END_TAG && depth == parser.getDepth()) {
- break;
- }
- }
- }
-
- @NonNull
- @Contract(" -> new")
- private Drawable unsupported() {
- return new TextDrawable("Unsupported drawable", displayMetrics);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ScaleDrawableParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ScaleDrawableParser.java
deleted file mode 100644
index 994e6f498..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ScaleDrawableParser.java
+++ /dev/null
@@ -1,109 +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.inflater.drawable;
-
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ScaleDrawable;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.InflateException;
-import com.itsaky.inflater.util.Preconditions;
-
-import org.xmlpull.v1.XmlPullParser;
-
-/**
- * Parser for parsing <scale> drawables.
- *
- * @author Akash Yadav
- */
-public class ScaleDrawableParser extends IDrawableParser {
-
- protected ScaleDrawableParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Override
- public Drawable parseDrawable() throws Exception {
- var index = attrIndex("drawable");
- if (index == -1) {
- throw new InflateException(" drawable must specify android:drawable attribute");
- }
- var v = value(index);
- Preconditions.assertNotBlank(v, "Invalid value specified for android:drawable attribute");
-
- final var drawable = parseDrawable(v, BaseApplication.getBaseInstance());
- if (drawable == null) {
- throw new InflateException("Unable to parse drawable: " + v);
- }
-
- var gravity = Gravity.LEFT;
- index = attrIndex("scaleGravity");
- if (index != -1) {
- try {
- gravity = parseGravity(value(index));
- } catch (Throwable th) {
- // ignored
- }
- }
-
- var scaleWidth = -1.0f;
- var scaleHeight = -1.0f; // DO_NOT_SCALE by default
-
- index = attrIndex("scaleWidth");
- if (index != -1) {
- try {
- scaleWidth = parseScale(value(index));
- } catch (Throwable th) {
- // ignored
- }
- }
-
- index = attrIndex("scaleHeight");
- if (index != -1) {
- try {
- scaleHeight = parseScale(value(index));
- } catch (Throwable th) {
- // ignored
- }
- }
-
- return new ScaleDrawable(drawable, gravity, scaleWidth, scaleHeight);
- }
-
- private float parseScale(@NonNull String value) {
- if (!value.endsWith("%")) {
- throw new InflateException("Invalid scale value:" + value);
- }
-
- final var factor = Float.parseFloat(value.substring(0, value.length() - 1)) / 100;
- if (factor < 0f || factor > 1f) {
- throw new InflateException("Scale factor must be between 0% and 100%");
- }
-
- return factor;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ShapeDrawableParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ShapeDrawableParser.java
deleted file mode 100644
index 6374c3854..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/ShapeDrawableParser.java
+++ /dev/null
@@ -1,358 +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.inflater.drawable;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.inflater.IResourceTable;
-
-import org.jetbrains.annotations.Contract;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.util.Arrays;
-
-/**
- * Parses a drawable whose root element is {@code }. If the parse was successful, returns a
- * {@link GradientDrawable}, otherwise {@code null}.
- *
- * @author Akash Yadav
- */
-public class ShapeDrawableParser extends IDrawableParser {
-
- protected ShapeDrawableParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Nullable
- @Override
- public Drawable parseDrawable() throws Exception {
-
- final var drawable = new GradientDrawable();
-
- var index = attrIndex("shape");
- drawable.setShape(
- index == -1
- ? GradientDrawable.RECTANGLE
- : parseShape(this.parser.getAttributeValue(index)));
-
- if (isApi29()) {
- index = attrIndex("innerRadius");
- drawable.setInnerRadius(index == -1 ? 0 : parseDimension(value(index), 0));
-
- index = attrIndex("innerRadiusRatio");
- drawable.setInnerRadiusRatio(index == -1 ? 1f : Float.parseFloat(value(index)));
-
- index = attrIndex("thickness");
- drawable.setThickness(index == -1 ? 0 : parseDimension(value(index), 0));
-
- index = attrIndex("thicknessRatio");
- drawable.setThicknessRatio(index == -1 ? 1f : Float.parseFloat(value(index)));
- }
-
- index = attrIndex("useLevel");
- drawable.setUseLevel(index != -1 && parseBoolean(value(index)));
-
- var event = parser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT && canParse()) {
- final var name = parser.getName();
- if (event == XmlPullParser.START_TAG) {
- switch (name) {
- case "corners":
- parseCorners(drawable);
- break;
- case "gradient":
- parseGradient(drawable);
- break;
- case "padding":
- parsePadding(drawable);
- break;
- case "size":
- parseSize(drawable);
- break;
- case "solid":
- parseSolid(drawable);
- break;
- case "stroke":
- parseStroke(drawable);
- break;
- }
- }
- event = parser.next();
- }
-
- return drawable;
- }
-
- private void parseStroke(@NonNull final GradientDrawable drawable) {
- var index = attrIndex("width");
- var strokeWidth = 0;
- if (index != -1) {
- drawable.setStroke(strokeWidth = parseDimension(value(index), 0), Color.TRANSPARENT);
- }
-
- index = attrIndex("color");
- var strokeColor = Color.TRANSPARENT;
- if (index != -1) {
- drawable.setStroke(strokeWidth, strokeColor = parseColor(value(index), appContext()));
- }
-
- index = attrIndex("dashWidth");
- var dashWidth = 0;
- if (index != -1) {
- drawable.setStroke(strokeWidth, strokeColor, dashWidth = parseDimension(value(index), 0), 0);
- }
-
- index = attrIndex("dashGap");
- if (index != -1) {
- drawable.setStroke(strokeWidth, strokeColor, dashWidth, parseDimension(value(index), 0));
- }
- }
-
- private void parseSolid(@NonNull final GradientDrawable drawable) {
- var index = attrIndex("color");
- if (index != -1) {
- drawable.setColor(parseColor(value(index), appContext()));
- }
- }
-
- private void parseSize(@NonNull final GradientDrawable drawable) {
- var index = attrIndex("width");
- if (index != -1) {
- drawable.setSize(parseDimension(value(index), 0), drawable.getIntrinsicHeight());
- }
-
- index = attrIndex("height");
- if (index != -1) {
- drawable.setSize(drawable.getIntrinsicWidth(), parseDimension(value(index), 0));
- }
- }
-
- private void parsePadding(@NonNull final GradientDrawable drawable) {
-
- // Padding is available from API 29 only
- if (!isApi29()) {
- return;
- }
-
- final var rect = new Rect();
- if (!drawable.getPadding(rect)) {
- rect.set(0, 0, 0, 0);
- }
-
- var changed = false;
- var index = attrIndex("left");
- if (index != -1) {
- rect.left = parseDimension(value(index), 0);
- changed = true;
- }
-
- index = attrIndex("top");
- if (index != -1) {
- rect.top = parseDimension(value(index), 0);
- changed = true;
- }
-
- index = attrIndex("right");
- if (index != -1) {
- rect.right = parseDimension(value(index), 0);
- changed = true;
- }
-
- index = attrIndex("bottom");
- if (index != -1) {
- rect.bottom = parseDimension(value(index), 0);
- changed = true;
- }
-
- if (changed) {
- drawable.setPadding(rect.left, rect.top, rect.right, rect.bottom);
- }
- }
-
- private void parseGradient(@NonNull final GradientDrawable drawable) {
- var index = attrIndex("angle");
- drawable.setOrientation(
- index == -1
- ? GradientDrawable.Orientation.LEFT_RIGHT
- : parseGradientOrientation(value(index)));
-
- index = attrIndex("centerX");
- var center = index == -1 ? drawable.getGradientCenterX() : Float.parseFloat(value(index));
- drawable.setGradientCenter(center, drawable.getGradientCenterY());
-
- index = attrIndex("centerY");
- center = index == -1 ? drawable.getGradientCenterX() : Float.parseFloat(value(index));
- drawable.setGradientCenter(drawable.getGradientCenterX(), center);
-
- final var colors = new int[3];
- var changed = false;
- Arrays.fill(colors, -1);
-
- index = attrIndex("centerColor");
- if (index != -1) {
- colors[1] = parseColor(value(index), appContext());
- changed = true;
- }
-
- index = attrIndex("endColor");
- if (index != -1) {
- colors[2] = parseColor(value(index), appContext());
- changed = true;
- }
-
- index = attrIndex("gradientRadius");
- drawable.setGradientRadius(
- index == -1 ? drawable.getGradientRadius() : Float.parseFloat(value(index)));
-
- index = attrIndex("startColor");
- if (index != -1) {
- colors[0] = parseColor(value(index), appContext());
- changed = true;
- }
-
- if (changed) {
- drawable.setColors(colors);
- }
-
- index = attrIndex("type");
- drawable.setGradientType(
- index == -1 ? GradientDrawable.LINEAR_GRADIENT : parseGradientType(value(index)));
-
- index = attrIndex("useLevel");
- drawable.setUseLevel(index != -1 && parseBoolean(value(index)));
- }
-
- private int parseGradientType(String value) {
- switch (value) {
- case "radial":
- return GradientDrawable.RADIAL_GRADIENT;
- case "sweep":
- return GradientDrawable.SWEEP_GRADIENT;
- case "linear":
- default:
- return GradientDrawable.LINEAR_GRADIENT;
- }
- }
-
- private GradientDrawable.Orientation parseGradientOrientation(String value) {
- final var angle = Integer.parseInt(value);
-
- // Angle must be between 0-315 and a multiple of 45
- // Angle moves in anti-clockwise direction
- if (angle == 45) {
- return GradientDrawable.Orientation.BL_TR;
- }
-
- if (angle == 90) {
- return GradientDrawable.Orientation.BOTTOM_TOP;
- }
-
- if (angle == 135) {
- return GradientDrawable.Orientation.BR_TL;
- }
-
- if (angle == 180) {
- return GradientDrawable.Orientation.RIGHT_LEFT;
- }
-
- if (angle == 225) {
- return GradientDrawable.Orientation.TR_BL;
- }
-
- if (angle == 270) {
- return GradientDrawable.Orientation.TOP_BOTTOM;
- }
-
- if (angle == 315) {
- return GradientDrawable.Orientation.TL_BR;
- }
-
- // Angle 0 or any invalid valid should make the orientation left to right
- return GradientDrawable.Orientation.LEFT_RIGHT;
- }
-
- protected Context appContext() {
- return BaseApplication.getBaseInstance();
- }
-
- private void parseCorners(@NonNull GradientDrawable drawable) {
- int index;
- index = attrIndex("radius");
- drawable.setCornerRadius(index == -1 ? 0f : parseDimension(value(index), 0));
-
- var changed = false;
- final var radii = new float[8];
- Arrays.fill(radii, 0f);
-
- index = attrIndex("topLeftRadius");
- if (index != -1) {
- radii[0] = radii[1] = parseDimension(value(index), 0);
- changed = true;
- }
-
- index = attrIndex("topRightRadius");
- if (index != -1) {
- radii[2] = radii[3] = parseDimension(value(index), 0);
- changed = true;
- }
-
- index = attrIndex("bottomLeftRadius");
- if (index != -1) {
- radii[4] = radii[5] = parseDimension(value(index), 0);
- changed = true;
- }
-
- index = attrIndex("bottomRightRadius");
- if (index != -1) {
- radii[6] = radii[7] = parseDimension(value(index), 0);
- changed = true;
- }
-
- if (changed) {
- drawable.setCornerRadii(radii);
- }
- }
-
- @Contract(pure = true)
- private int parseShape(@NonNull String value) {
- switch (value) {
- case "oval":
- return GradientDrawable.OVAL;
- case "line":
- return GradientDrawable.LINE;
- case "ring":
- return GradientDrawable.RING;
- case "rectangle":
- default:
- return GradientDrawable.RECTANGLE;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/StateListParser.java b/xml-inflater/src/main/java/com/itsaky/inflater/drawable/StateListParser.java
deleted file mode 100644
index c3b5494bd..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/drawable/StateListParser.java
+++ /dev/null
@@ -1,132 +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.inflater.drawable;
-
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.util.DisplayMetrics;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.InflateException;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import java.util.ArrayList;
-
-/**
- * Parser for parsing <selector> drawables.
- *
- * @author Akash Yadav
- */
-public class StateListParser extends IDrawableParser {
-
- private static final ILogger LOG = ILogger.newInstance("StateListParser");
-
- protected StateListParser(
- XmlPullParser parser,
- IResourceTable resourceFinder,
- DisplayMetrics displayMetrics,
- int minDepth) {
- super(parser, resourceFinder, displayMetrics, minDepth);
- }
-
- @Override
- public Drawable parseDrawable() throws Exception {
- var states = new StateListDrawable();
-
- // --------------------------- NOTE -------------------------
- // Unsupported attributes :
- // 1. android:constantSize
- // 2. android:variablePadding
-
- var index = attrIndex("dither");
- if (index != -1) {
- states.setDither(parseBoolean(value(index)));
- }
-
- var event = parser.getEventType();
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- var name = parser.getName();
- if ("item".equals(name)) {
- index = attrIndex("drawable");
- if (index == -1) {
- throw new InflateException(" item does not define android:drawable");
- }
- final var drawable = parseDrawable(value(index), BaseApplication.getBaseInstance());
- if (drawable == null) {
- throw new InflateException("Unable to parse drawable for android:drawable attribute");
- }
-
- addStates(states, drawable);
- }
- }
- }
-
- return states;
- }
-
- /**
- * Add all the defined states of the current tag in
parser to the given state list
- * drawable.
- *
- * @param states The drawable to add states to.
- * @param drawable The drawable associated with the defined states;
- */
- private void addStates(StateListDrawable states, Drawable drawable) {
- final var stateList = new ArrayList();
- final var count = parser.getAttributeCount();
- for (int i = 0; i < count; i++) {
- var name = parser.getAttributeName(i);
- var value = parser.getAttributeValue(i);
- if (!name.startsWith("state_")) {
- continue;
- }
-
- var state = reflectState(name);
-
- final var isEnabled = parseBoolean(value);
- if (!isEnabled) {
- // android:state_[state_name]="false"
- state = -state;
- }
-
- stateList.add(state);
- }
-
- final var arr = new int[stateList.size()];
- for (int i = 0; i < stateList.size(); i++) {
- arr[i] = stateList.get(i);
- }
-
- states.addState(arr, drawable);
- }
-
- private int reflectState(String name) {
- try {
- final var clazz = android.R.attr.class;
- final var field = clazz.getDeclaredField(name);
- return field.getInt(null);
- } catch (Throwable th) {
- LOG.error("Unable to get state ID with name:", name);
- return -1;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/BaseView.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/BaseView.java
deleted file mode 100644
index efc83a58c..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/BaseView.java
+++ /dev/null
@@ -1,347 +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.inflater.impl;
-
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.inflater.IAttributeAdapter;
-import com.itsaky.inflater.IView;
-import com.itsaky.inflater.IViewGroup;
-import com.itsaky.xml.INamespace;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
-public abstract class BaseView implements IView {
-
- public static final String XML_HEADER = "";
-
- protected final Set namespaces =
- new TreeSet<>(Comparator.comparing(INamespace::getPrefix));
- protected final List attributes = new ArrayList<>();
- protected final Set attrAdapters = new HashSet<>();
-
- protected final String qualifiedName;
- protected final View view;
- protected final ILogger LOG = ILogger.newInstance(getClass().getSimpleName());
- protected IViewGroup parent;
- protected Object stored;
- private boolean isPlaceholder;
-
- public BaseView(String qualifiedName, View view) {
- this(qualifiedName, view, false);
- }
-
- public BaseView(String qualifiedName, View view, boolean isPlaceholder) {
- this.qualifiedName = qualifiedName;
- this.view = view;
- this.isPlaceholder = isPlaceholder;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(
- attributes, attrAdapters, qualifiedName, view, getParent(), stored, isPlaceholder());
- }
-
- @Override
- public void setParent(IViewGroup parent) {
- this.parent = parent;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- BaseView baseView = (BaseView) o;
- return isPlaceholder() == baseView.isPlaceholder()
- && Objects.equals(attributes, baseView.attributes)
- && Objects.equals(attrAdapters, baseView.attrAdapters)
- && Objects.equals(qualifiedName, baseView.qualifiedName)
- && Objects.equals(view, baseView.view)
- && Objects.equals(getParent(), baseView.getParent())
- && Objects.equals(stored, baseView.stored);
- }
-
- public void setPlaceholder(boolean placeholder) {
- this.isPlaceholder = placeholder;
- }
-
- protected Set getAttributeAdapters() {
- return attrAdapters;
- }
-
- @Override
- public boolean isPlaceholder() {
- return isPlaceholder;
- }
-
- @Override
- public View asView() {
- return view;
- }
-
- @Override
- public IViewGroup getParent() {
- return parent;
- }
-
- @Override
- public boolean removeFromParent() {
- if (getParent() != null) {
- getParent().removeView(this);
- return true;
- }
-
- LOG.info("View does not have a parent. Cannot remove.");
- return false;
- }
-
- @Override
- public void addAttribute(IAttribute attr) {
- if (attr == null || this.attributes.contains(attr)) {
- return;
- }
-
- this.attributes.add(attr);
-
- applyAttributeValue(attr);
-
- this.attributes.sort(IAttribute.COMPARATOR);
- }
-
- private void applyAttributeValue(final IAttribute attr) {
- for (IAttributeAdapter adapter : attrAdapters) {
- if (adapter.isApplicableTo(asView()) && adapter.apply(attr, asView())) {
- break;
- }
- }
- }
-
- @Override
- public void removeAttribute(IAttribute attr) {
- this.attributes.remove(attr);
- }
-
- @Override
- public void removeAttributeAt(int index) {
- this.attributes.remove(index);
- }
-
- @Override
- public List getAttributes() {
- return attributes;
- }
-
- @Override
- public IAttribute[] getAttrArray() {
- return getAttributes().toArray(new IAttribute[0]);
- }
-
- @Override
- public boolean hasAttribute(INamespace namespace, String name) {
- return this.attributes.stream()
- .anyMatch(
- attribute ->
- Objects.equals(attribute.getNamespace(), namespace)
- && attribute.getAttributeName().equals(name));
- }
-
- @Nullable
- @Override
- public IAttribute getAttribute(INamespace namespace, String name) {
- for (var attr : this.attributes) {
- if (Objects.equals(attr.getNamespace(), namespace) && attr.getAttributeName().equals(name)) {
- return attr;
- }
- }
- return null;
- }
-
- @Override
- public boolean updateAttribute(INamespace namespace, String name, String value) {
- IAttribute found = null;
- int index = -1;
- for (int i = 0; i < attributes.size(); i++) {
- final var attr = attributes.get(i);
- if (Objects.equals(attr.getNamespace(), namespace) && attr.getAttributeName().equals(name)) {
- found = attr;
- index = i;
- break;
- }
- }
-
- if (found != null && index < this.attributes.size()) {
- found.apply(value);
- this.attributes.set(index, found);
- // Let the attribute adapters handle the update
- applyAttributeValue(found);
-
- return true;
- }
-
- return false;
- }
-
- @Override
- public void registerAttributeAdapter(IAttributeAdapter adapter) {
- if (adapter == null) {
- return;
- }
-
- this.attrAdapters.add(adapter);
- }
-
- @Override
- public void setExtraData(Object data) {
- this.stored = data;
- }
-
- @Nullable
- @Override
- public Object getExtraData() {
- return this.stored;
- }
-
- @Override
- public String getXmlTag() {
- return Objects.requireNonNull(asView()).getClass().getSimpleName();
- }
-
- @Override
- public void registerNamespace(INamespace namespace) {
- this.namespaces.add(namespace);
- }
-
- @Nullable
- @Override
- public INamespace findRegisteredNamespace(@NonNull String name) {
- final var namespaces =
- this.namespaces.stream()
- .filter(ns -> name.equals(ns.getPrefix()))
- .collect(Collectors.toSet());
-
- if (namespaces.isEmpty()) {
-
- // If the namespace was not declared in this view,
- // check if it was declared in parent
- if (getParent() != null) {
- return getParent().findRegisteredNamespace(name);
- }
-
- return null;
- }
-
- return namespaces.iterator().next();
- }
-
- /**
- * Generate the XML layout code for this view.
- *
- * NOTE: To avoid writing same logic in multiple files, this implementation tries to handle
- * logic for both {@link IView} and {@link IViewGroup}.
- *
- *
For example, if this view is an {@link IViewGroup}, then the layout code for its children
- * will also be printed.
- *
- * @param indentCount The number of tabs to indent. To define custom tab size, see {@link
- * IView#DEFAULT_INDENTATION_LENGTH}.
- * @return The generated XML code. Never null.
- */
- @NonNull
- @Override
- public String generateCode(int indentCount) {
- final var sb = new StringBuilder();
- sb.append("<");
- sb.append(getXmlTag());
-
- if (!attributes.isEmpty()) {
- for (var attr : attributes) {
- newLine(sb, indentCount + 1); // Attributes must be indented by one tab (4 spaces by
- // default)
- attr.getNamespace();
- if (attr.getNamespace() != null && attr.getNamespace().getPrefix().length() > 0) {
- sb.append(attr.getNamespace().getPrefix());
- sb.append(":");
- }
- sb.append(attr.getAttributeName());
- sb.append("=");
- sb.append("\"");
- sb.append(attr.getValue());
- sb.append("\"");
- }
- }
-
- var hasChildren = false;
- if (this instanceof IViewGroup) {
- final var group = (IViewGroup) this;
- hasChildren = group.getChildCount() > 0;
-
- if (hasChildren) {
- sb.append(">");
- newLine(sb, indentCount + 1);
-
- for (var child : group.getChildren()) {
- newLine(sb, indentCount + 1);
- sb.append(child.generateCode(indentCount + 1));
- newLine(sb, indentCount + 1);
- }
- }
- }
-
- if (hasChildren) {
- // Closing '>' is already printed, no need to print it here.
- // Leave one line and append the closing tag.
- newLine(sb, indentCount);
- newLine(sb, indentCount);
- sb.append("");
- sb.append(getXmlTag());
- sb.append(">");
- } else {
- sb.append("/>");
- }
-
- return sb.toString();
- }
-
- protected void newLine(@NonNull StringBuilder stringBuilder, int indentCount) {
- stringBuilder.append("\n");
- indent(stringBuilder, indentCount);
- }
-
- protected void indent(StringBuilder sb, int count) {
- for (var i = 0; i < DEFAULT_INDENTATION_LENGTH * count; i++) {
- sb.append(" ");
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/BaseViewGroup.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/BaseViewGroup.java
deleted file mode 100644
index 898b0491a..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/BaseViewGroup.java
+++ /dev/null
@@ -1,112 +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.inflater.impl;
-
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttributeAdapter;
-import com.itsaky.inflater.IView;
-import com.itsaky.inflater.IViewGroup;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public abstract class BaseViewGroup extends BaseView implements IViewGroup {
-
- protected final List mHierarchyChangeListeners = new ArrayList<>();
-
- public BaseViewGroup(String qualifiedName, ViewGroup view) {
- this(qualifiedName, view, false);
- }
-
- public BaseViewGroup(String qualifiedName, ViewGroup view, boolean isPlaceholder) {
- super(qualifiedName, view, isPlaceholder);
- }
-
- @Override
- public boolean isPlaceholder() {
- return false; // We do not use view groups as placeholder
- }
-
- @Override
- public void addView(IView view, int index) {
- for (IAttributeAdapter adapter : getAttributeAdapters()) {
- view.registerAttributeAdapter(adapter);
- }
- }
-
- @Override
- public int indexOfChild(@NonNull IView view) {
- return indexOfChild(view.asView());
- }
-
- @Override
- public int indexOfChild(View view) {
- for (var i = 0; i < getChildCount(); i++) {
- final var child = getChildAt(i);
- if (child != null
- && child.asView() != null
- && child.asView() == view) { // Comparison is same in ViewGroup implementation
- return i;
- }
- }
- return -1;
- }
-
- @Override
- public void registerHierarchyChangeListener(OnHierarchyChangeListener listener) {
- if (listener == null) {
- return;
- }
- this.mHierarchyChangeListeners.add(listener);
- }
-
- @Override
- public void unregisterHierarchyChangeListener(OnHierarchyChangeListener listener) {
- if (listener == null) {
- return;
- }
-
- this.mHierarchyChangeListeners.remove(listener);
- }
-
- /**
- * Called when a new view has been added to this group
- *
- * @param view The view that was added
- */
- protected void onViewAdded(IView view) {
- for (OnHierarchyChangeListener listener : this.mHierarchyChangeListeners) {
- listener.onViewAdded(view);
- }
- }
-
- /**
- * Called when a new view has been removed from this group
- *
- * @param view The view that was removed
- */
- protected void onViewRemoved(IView view) {
- for (OnHierarchyChangeListener listener : this.mHierarchyChangeListeners) {
- listener.onViewRemoved(view);
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/ErrorUiView.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/ErrorUiView.java
deleted file mode 100644
index 1b343a940..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/ErrorUiView.java
+++ /dev/null
@@ -1,104 +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.inflater.impl;
-
-import android.content.Context;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-
-import com.itsaky.inflater.IView;
-
-import org.jetbrains.annotations.Contract;
-
-/**
- * A view which is used to show views that cannot be inflated. This view will preserve the
- * attributes and the children if the view is a view group;
- *
- * @author Akash Yadav
- */
-public class ErrorUiView extends UiViewGroup {
-
- private ErrorUiView(String qualifiedName, ViewGroup view) {
- super(qualifiedName, view);
- }
-
- private ErrorUiView(String qualifiedName, ViewGroup view, boolean isPlaceholder) {
- super(qualifiedName, view, isPlaceholder);
- }
-
- /**
- * Create a new error view for the given qualified name of the view that was not inflated
- * correctly.
- *
- * We add a text directly in this view. Any other views that will be added to this group will
- * have visibility {@link View#GONE} by default.
- *
- * @param context The context that will be used to create the view.
- * @param name The qualified name of the view that was not inflated.
- * @param message The message that should be shown to the user.
- * @return A newly created instance of the error view.
- */
- @NonNull
- @Contract("_, _, _ -> new")
- public static IView create(
- @NonNull final Context context, @NonNull final String name, @NonNull final String message) {
- final var container = new LinearLayout(context);
- final var error = new TextView(context);
- error.setText(message);
- error.setLayoutParams(new ViewGroup.LayoutParams(-2, -2));
- error.setTextColor(ContextCompat.getColor(context, android.R.color.black));
- error.setBackgroundColor(ContextCompat.getColor(context, android.R.color.white));
-
- container.setOrientation(LinearLayout.HORIZONTAL);
- container.addView(
- error,
- new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
-
- return new ErrorUiView(name, container, true);
- }
-
- @Override
- public void addView(IView view, int index) {
- super.addView(view, index);
- view.asView().setVisibility(View.GONE);
- }
-
- @Override
- public int getChildCount() {
- return super.getChildCount() - 1;
- }
-
- @Override
- public String getXmlTag() {
- // This might be a custom view or something
- // So return the qualified name of the view
- return this.qualifiedName;
- }
-
- @NonNull
- @Override
- public String generateCode(int indentCount) {
- return super.generateCode(indentCount);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/IncludeLayout.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/IncludeLayout.java
deleted file mode 100644
index b5bab46e7..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/IncludeLayout.java
+++ /dev/null
@@ -1,41 +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.inflater.impl;
-
-import com.itsaky.inflater.IView;
-
-/**
- * Layout model for <include> tags.
- *
- * @author Akash Yadav
- */
-public class IncludeLayout extends BaseView {
-
- public static final String TAG = "include";
- private final IView view;
-
- public IncludeLayout(IView view) {
- super(TAG, view.asView(), false);
- this.view = view;
- }
-
- @Override
- public String getXmlTag() {
- return TAG;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiAttribute.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiAttribute.java
deleted file mode 100644
index 9baeef8da..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiAttribute.java
+++ /dev/null
@@ -1,93 +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.inflater.impl;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.IAttribute;
-import com.itsaky.xml.INamespace;
-
-import java.util.Objects;
-
-public class UiAttribute implements IAttribute {
-
- private final INamespace namespace;
- private final String name;
- protected String value;
-
- public UiAttribute(INamespace namespace, String name, String value) {
- this.namespace = namespace;
- this.name = name;
- this.value = value;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getNamespace(), name, getValue());
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- UiAttribute that = (UiAttribute) o;
- return Objects.equals(getNamespace(), that.getNamespace())
- && Objects.equals(name, that.name)
- && Objects.equals(getValue(), that.getValue());
- }
-
- @NonNull
- @Override
- public INamespace getNamespace() {
- return namespace;
- }
-
- @NonNull
- @Override
- public String getAttributeName() {
- return name;
- }
-
- @NonNull
- @Override
- public String getValue() {
- return this.value;
- }
-
- @Override
- public void apply(String value) {
- this.value = value;
- }
-
- @NonNull
- @Override
- public String toString() {
- return "UiAttribute ["
- + "\n"
- + " namespace = "
- + namespace
- + "\n"
- + " name = "
- + name
- + "\n"
- + " value = "
- + value
- + "\n"
- + "]";
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiView.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiView.java
deleted file mode 100644
index 2222bb931..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiView.java
+++ /dev/null
@@ -1,31 +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.inflater.impl;
-
-import android.view.View;
-
-public class UiView extends BaseView {
-
- public UiView(String qualifiedName, View view) {
- this(qualifiedName, view, false);
- }
-
- public UiView(String qualifiedName, View view, boolean isPlaceholder) {
- super(qualifiedName, view, isPlaceholder);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiViewGroup.java b/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiViewGroup.java
deleted file mode 100644
index 1de762b88..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/impl/UiViewGroup.java
+++ /dev/null
@@ -1,110 +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.inflater.impl;
-
-import android.view.ViewGroup;
-
-import androidx.annotation.Nullable;
-
-import com.itsaky.inflater.IView;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-public class UiViewGroup extends BaseViewGroup {
-
- private final ViewGroup viewGroup;
- private final List children;
-
- public UiViewGroup(String qualifiedName, ViewGroup view) {
- this(qualifiedName, view, false);
- }
-
- public UiViewGroup(String qualifiedName, ViewGroup view, boolean isPlaceholder) {
- super(qualifiedName, view, isPlaceholder);
-
- this.viewGroup = view;
- this.children = new ArrayList<>();
- }
-
- @Override
- public void addView(IView view) {
- addView(view, getChildCount());
- }
-
- @Override
- public void addView(IView view, int index) {
- super.addView(view, index);
- this.viewGroup.addView(view.asView(), index);
- this.children.add(index, view);
-
- view.setParent(this);
- onViewAdded(view);
- }
-
- @Override
- public void removeView(int index) {
- final IView view = children.get(index);
- removeView(view);
- }
-
- @Override
- public void removeView(@Nullable IView view) {
- if (view == null) {
- LOG.warn("Null view passed to IViewGroup.removeView(IView). Ignoring.");
- return;
- }
-
- this.viewGroup.removeView(view.asView());
- this.children.remove(view);
-
- view.setParent(null);
- onViewRemoved(view);
- }
-
- @Override
- public void removeAll() {
- for (var child : this.children) {
- // Remove each view individually
- // This will make sure that we set the parent of the children to null
- // and call #onViewRemoved (IView)
- removeView(child);
- }
- }
-
- @Override
- public void forEachChild(Consumer consumer) {
- this.children.stream().forEach(consumer);
- }
-
- @Override
- public int getChildCount() {
- return this.viewGroup.getChildCount();
- }
-
- @Override
- public List getChildren() {
- return this.children;
- }
-
- @Override
- public IView getChildAt(int index) {
- return children.get(index);
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/util/CommonParseUtils.java b/xml-inflater/src/main/java/com/itsaky/inflater/util/CommonParseUtils.java
deleted file mode 100644
index e068ecfe8..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/util/CommonParseUtils.java
+++ /dev/null
@@ -1,419 +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.inflater.util;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
-import androidx.core.view.GravityCompat;
-
-import com.itsaky.androidide.app.BaseApplication;
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.IResourceTable;
-import com.itsaky.inflater.drawable.DrawableParserFactory;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * Contains methods which are commonly used by layout inflater, attribute adapters and drawable
- * parsers.
- *
- * @author Akash Yadav
- */
-public class CommonParseUtils {
-
- private static final Pattern HEX_COLOR = Pattern.compile("#[a-fA-F0-9]{6,8}");
- private static final ILogger LOG = ILogger.newInstance("CommonParseUtils");
- protected final DisplayMetrics displayMetrics;
- protected IResourceTable resourceFinder;
-
- public CommonParseUtils(@NonNull IResourceTable resourceFinder, DisplayMetrics displayMetrics) {
- this.resourceFinder = resourceFinder;
- this.displayMetrics = displayMetrics;
- }
-
- public int parseColor(String color, final Context ctx) {
- if (HEX_COLOR.matcher(color).matches()) {
- try {
- return Color.parseColor(color);
- } catch (Throwable th) {
- // Ignored
- }
- } else if (color.startsWith("@color/")) {
-
- return parseColor(resourceFinder.findColor(color.substring("@color/".length())), ctx);
- } else if (color.startsWith("@android:color/")) {
- final int id = findFrameworkResourceId("color", color.substring("@android:color/".length()));
- return ContextCompat.getColor(ctx, id);
- }
-
- return Color.TRANSPARENT;
- }
-
- protected String[] parseArray(final String value) {
- if (value.startsWith("@android:array/")) {
- final var name = value.substring("@android:array/".length());
- return frameworkArrayValue(name);
- } else if (value.startsWith("@array/")) {
- final var name = value.substring("@array/".length());
- return resourceFinder.findArray(name);
- } else {
- return new String[] {value};
- }
- }
-
- private String[] frameworkArrayValue(String name) {
- try {
- final var id = findFrameworkResourceId("array", name);
- if (id == -1) {
- return new String[] {name};
- }
-
- return BaseApplication.getBaseInstance().getResources().getStringArray(id);
- } catch (Throwable th) {
- return new String[0];
- }
- }
-
- private int findFrameworkResourceId(String type, String name) {
- try {
- final Class> typeClass =
- Objects.requireNonNull(
- android.R.class.getClassLoader(),
- "Unable to get class loader for loading system resources")
- .loadClass("android.R$" + type);
- final Field typeField = typeClass.getDeclaredField(name);
- typeField.setAccessible(true);
- return typeField.getInt(null);
- } catch (Throwable th) {
- LOG.error("Unable to find framework resource.", "type=" + type, "name=" + name);
- return -1;
- }
- }
-
- protected String parseString(@NonNull String value) {
- if (value.startsWith("@string/")) {
- return parseString(resourceFinder.findString(value.substring("@string/".length())));
- } else if (value.startsWith("@android:string/")) {
- return frameworkStringValue(value.substring("@android:string/".length()));
- } else {
- return value;
- }
- }
-
- protected boolean parseBoolean(@NonNull String value) {
- if (!value.startsWith("@")) {
- if ("true".equals(value)) {
- return true;
- } else if ("false".equals(value)) {
- return false;
- }
- } else if (value.startsWith("@bool/")) {
- return parseBoolean(resourceFinder.findBoolean(value.substring("@bool/".length())));
- } else if (value.startsWith("@android:bool/")) {
- final var name = value.substring("@android:bool/".length());
- return frameworkBooleanValue(name);
- }
- return false;
- }
-
- protected int parseInteger(@NonNull String value, int defaultVal) {
- if (value.startsWith("@integer/")) {
- return parseInteger(
- resourceFinder.findInteger(value.substring("@integer/".length())), defaultVal);
- } else if (value.startsWith("@android:integer/")) {
- final var name = value.substring("@android:integer/".length());
- return frameworkIntegerResource(name, defaultVal);
- } else {
- try {
- return Integer.parseInt(value);
- } catch (Throwable th) {
- return defaultVal;
- }
- }
- }
-
- protected int parseDimension(final String value, int defaultValue) {
- if (value == null || value.isEmpty()) {
- return defaultValue;
- }
-
- char c = value.charAt(0);
- if (Character.isDigit(c)) {
- // A dimension value which starts with a digit. E.g.: 1dp, 12sp, 123px, etc.
- StringBuilder dimensionVal = new StringBuilder();
- int index = 0;
- while (Character.isDigit(c = value.charAt(index))) {
- dimensionVal.append(c);
- index++;
- }
-
- final int dimen = Integer.parseInt(dimensionVal.toString());
- final String dimensionType = value.substring(index);
- return (int)
- TypedValue.applyDimension(getUnitForDimensionType(dimensionType), dimen, displayMetrics);
- } else if (c == '@') {
- if (value.startsWith("@android:dimen/")) {
- final var name = value.substring("@android:dimen/".length());
- return frameworkDimensionValue(name, defaultValue);
- } else if (value.startsWith("@dimen/")) {
- String name = value.substring("@dimen/".length());
- return parseDimension(resourceFinder.findDimension(name), defaultValue);
- }
- } else if (Character.isLetter(c)) {
- // This could be one of the following :
- // 1. match_parent
- // 2. wrap_content
- // 3. fill_parent
- switch (value) {
- case "match_parent":
- case "fill_parent":
- return ViewGroup.LayoutParams.MATCH_PARENT;
- case "wrap_content":
- default:
- return ViewGroup.LayoutParams.WRAP_CONTENT;
- }
- }
-
- return defaultValue;
- }
-
- protected int getUnitForDimensionType(@NonNull String dimensionType) {
-
- switch (dimensionType) {
- case "dp":
- return TypedValue.COMPLEX_UNIT_DIP;
- case "sp":
- return TypedValue.COMPLEX_UNIT_SP;
- case "px":
- return TypedValue.COMPLEX_UNIT_PX;
- case "pt":
- return TypedValue.COMPLEX_UNIT_PT;
- case "in":
- return TypedValue.COMPLEX_UNIT_IN;
- case "mm":
- return TypedValue.COMPLEX_UNIT_MM;
- }
-
- return TypedValue.COMPLEX_UNIT_DIP;
- }
-
- protected ColorStateList parseColorStateList(@NonNull String value, Context context) {
- if (HEX_COLOR.matcher(value).matches()) {
- return ColorStateList.valueOf(Color.parseColor(value));
- } else if (value.startsWith("@color/")) {
- final var name = value.substring("@color/".length());
- final var res = resourceFinder.findColor(name);
- final var color = parseColor(res, context);
- return ColorStateList.valueOf(color);
- } else if (value.startsWith("@android:color/")) {
- final var name = value.substring("@android:color/".length());
- final var id = findFrameworkResourceId("color", name);
- if (id == -1) {
- return ColorStateList.valueOf(Color.TRANSPARENT);
- }
- try {
- return ContextCompat.getColorStateList(context, id);
- } catch (Throwable th) {
- try {
- return ColorStateList.valueOf(ContextCompat.getColor(context, id));
- } catch (Throwable th2) {
- LOG.error("Unable to create color state list for framework resource", name);
- return ColorStateList.valueOf(Color.TRANSPARENT);
- }
- }
- }
-
- return ColorStateList.valueOf(Color.TRANSPARENT);
- }
-
- protected Drawable parseDrawable(String value, final Context ctx) {
- if (HEX_COLOR.matcher(value).matches()) {
- return drawableForColor(value);
- } else if (value.startsWith("@")) {
-
- // First check if this is a reference to an android resource
- if (value.startsWith("@android:")) {
- final String typeAndValue = value.substring("@android:".length());
- final String[] split =
- typeAndValue.split(
- Pattern.quote("/")); // For @android:color/white, it will be ["color",
- // "white"]
- final String type = split[0];
- final String typeVal = split[1];
- final int id = findFrameworkResourceId(type, typeVal);
-
- if (id != -1) {
- switch (type) {
- case "color":
- return drawableForColor(ContextCompat.getColor(ctx, id));
- case "drawable":
- return ContextCompat.getDrawable(ctx, id);
- default:
- return newTransparentDrawable();
- }
- }
-
- } else {
- // We found a reference to another resource
- if (value.startsWith("@drawable/")) {
- final File drawable = resourceFinder.findDrawable(value.substring("@drawable/".length()));
-
- if (drawable == null) {
- return null;
- }
-
- try {
- final var parser = DrawableParserFactory.newParser(ctx, drawable, resourceFinder);
- if (parser == null) {
- return null;
- }
- return parser.parse();
- } catch (Exception e) {
- LOG.error("Error parsing drawable", e);
- return null;
- }
-
- } else if (value.startsWith("@color/")) {
- final String color = resourceFinder.findColor(value.substring("@color/".length()));
- return new ColorDrawable(parseColor(color, ctx));
- }
- }
- }
- return newTransparentDrawable();
- }
-
- protected Drawable drawableForColor(String color) {
- try {
- return drawableForColor(Color.parseColor(color));
- } catch (Throwable th) {
- return newTransparentDrawable();
- }
- }
-
- protected Drawable drawableForColor(int color) {
- return new ColorDrawable(color);
- }
-
- protected Drawable newTransparentDrawable() {
- return new ColorDrawable(Color.TRANSPARENT);
- }
-
- protected int parseGravity(@NonNull String value) {
- final String[] splits = value.split(Pattern.quote("|"));
- int result = -1;
- for (String split : splits) {
- final int gravity = gravityFor(split);
- if (result == -1) {
- result = gravity;
- } else {
- result |= gravity;
- }
- }
- return result;
- }
-
- protected int gravityFor(@NonNull String gravity) {
- switch (gravity) {
- case "center":
- return Gravity.CENTER;
- case "center_vertical":
- return Gravity.CENTER_VERTICAL;
- case "center_horizontal":
- return Gravity.CENTER_HORIZONTAL;
- case "left":
- return Gravity.LEFT;
- case "right":
- return Gravity.RIGHT;
- case "top":
- return Gravity.TOP;
- case "bottom":
- return Gravity.BOTTOM;
- case "start":
- return GravityCompat.START;
- case "end":
- return GravityCompat.END;
- default:
- return Gravity.TOP | Gravity.START;
- }
- }
-
- private String frameworkStringValue(String name) {
- try {
- final var id = findFrameworkResourceId("string", name);
- if (id == -1) {
- return "";
- }
-
- return BaseApplication.getBaseInstance().getString(id);
- } catch (Throwable th) {
- return "";
- }
- }
-
- private boolean frameworkBooleanValue(String name) {
- try {
- final var id = findFrameworkResourceId("boolean", name);
- if (id == -1) {
- return false;
- }
-
- return BaseApplication.getBaseInstance().getResources().getBoolean(id);
- } catch (Throwable th) {
- return false;
- }
- }
-
- private int frameworkIntegerResource(String name, int defaultVal) {
- try {
- final var id = findFrameworkResourceId("integer", name);
- if (id == -1) {
- return defaultVal;
- }
-
- return BaseApplication.getBaseInstance().getResources().getInteger(id);
- } catch (Throwable th) {
- return defaultVal;
- }
- }
-
- private int frameworkDimensionValue(String name, int defValue) {
- try {
- final var id = findFrameworkResourceId("dimen", name);
- if (id == -1) {
- return defValue;
- }
-
- return (int) BaseApplication.getBaseInstance().getResources().getDimension(id);
- } catch (Throwable th) {
- return defValue;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/util/Preconditions.java b/xml-inflater/src/main/java/com/itsaky/inflater/util/Preconditions.java
deleted file mode 100644
index cc6053164..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/util/Preconditions.java
+++ /dev/null
@@ -1,52 +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.inflater.util;
-
-import com.itsaky.inflater.InflateException;
-
-public class Preconditions {
-
- public static void assertAllNotNull(String msg, Object... objs) {
- int i = 0;
- for (Object obj : objs) {
- if (obj == null) {
- throw new NullPointerException("[" + i + "] " + msg);
- }
- ++i;
- }
- }
-
- public static void assertNotBlank(String str, String msg) throws InflateException {
- Preconditions.assertNotnull(str, msg);
- if (str.trim().length() <= 0) {
- throw new InflateException(msg);
- }
- }
-
- public static void assertNotnull(Object obj, String msg) throws InflateException {
- if (obj == null) {
- throw new NullPointerException(msg);
- }
- }
-
- public static void assertTrue(boolean condition, String message) {
- if (!condition) {
- throw new AssertionError(message);
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/util/TextDrawable.java b/xml-inflater/src/main/java/com/itsaky/inflater/util/TextDrawable.java
deleted file mode 100644
index e6da52f8d..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/util/TextDrawable.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.itsaky.inflater.util;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-
-import androidx.annotation.NonNull;
-
-public class TextDrawable extends Drawable {
- private static final int DEFAULT_COLOR = Color.WHITE;
- private static final int DEFAULT_TEXT_SIZE = 15;
- private final Paint mPaint;
- private final CharSequence mText;
- private final int mIntrinsicWidth;
- private final int mIntrinsicHeight;
-
- public TextDrawable(CharSequence text, @NonNull DisplayMetrics displayMetrics) {
- mText = text;
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaint.setColor(DEFAULT_COLOR);
- mPaint.setTextAlign(Align.CENTER);
- float textSize =
- TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, DEFAULT_TEXT_SIZE, displayMetrics);
- mPaint.setTextSize(textSize);
- mIntrinsicWidth = (int) (mPaint.measureText(mText, 0, mText.length()) + .5);
- mIntrinsicHeight = mPaint.getFontMetricsInt(null);
- }
-
- @Override
- public void draw(Canvas canvas) {
- Rect bounds = getBounds();
- canvas.drawText(mText, 0, mText.length(), bounds.centerX(), bounds.centerY(), mPaint);
- }
-
- @Override
- public void setAlpha(int alpha) {
- mPaint.setAlpha(alpha);
- }
-
- @Override
- public void setColorFilter(ColorFilter filter) {
- mPaint.setColorFilter(filter);
- }
-
- @Override
- public int getOpacity() {
- return mPaint.getAlpha();
- }
-
- @Override
- public int getIntrinsicWidth() {
- return mIntrinsicWidth;
- }
-
- @Override
- public int getIntrinsicHeight() {
- return mIntrinsicHeight;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java
deleted file mode 100644
index 210b87d52..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java
+++ /dev/null
@@ -1,86 +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.inflater.values;
-
-import static java.lang.reflect.Modifier.isPublic;
-import static java.lang.reflect.Modifier.isStatic;
-
-import androidx.annotation.NonNull;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Provides framework resource values.
- *
- * @author Akash Yadav
- */
-public class FrameworkValues {
-
- @NonNull
- public static List listDimens() {
- return listFields(android.R.dimen.class);
- }
-
- @NonNull
- private static List listFields(final Class> klass) {
- Objects.requireNonNull(klass);
-
- final var list = new ArrayList();
- final var fields = klass.getDeclaredFields();
- for (var field : fields) {
- final var mods = field.getModifiers();
- if (!isPublic(mods) || !isStatic(mods)) {
- continue;
- }
-
- list.add(field.getName());
- }
-
- return list;
- }
-
- @NonNull
- public static List listBools() {
- return listFields(android.R.bool.class);
- }
-
- @NonNull
- public static List listStrings() {
- return listFields(android.R.string.class);
- }
-
- @NonNull
- public static List listColors() {
- return listFields(android.R.color.class);
- }
-
- @NonNull
- public static List listAllResources() {
- final var list = new ArrayList();
- for (var klass : android.R.class.getDeclaredClasses()) {
- list.addAll(
- listFields(klass).stream()
- .map(("@android:" + klass.getSimpleName() + "/")::concat)
- .collect(Collectors.toList()));
- }
- return list;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/IResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/IResource.java
deleted file mode 100644
index 4ce7fe3dc..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/IResource.java
+++ /dev/null
@@ -1,45 +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.inflater.values;
-
-import androidx.annotation.NonNull;
-
-/**
- * Base class for value entries in "res/values" directory.
- *
- * @author Akash Yadav
- */
-public interface IResource {
-
- /**
- * Get the unique identifier (name) of this resource. Defined by "name" attribute in resource
- * value entries in xml files.
- *
- * @return The name of this value.
- */
- @NonNull
- String getName();
-
- /**
- * Get the value of this resource entry.
- *
- * @return The value of this resource.
- */
- @NonNull
- String getValue();
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java
deleted file mode 100644
index 87ddc8992..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java
+++ /dev/null
@@ -1,410 +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.inflater.values;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.blankj.utilcode.util.FileUtils;
-import com.itsaky.androidide.utils.ILogger;
-import com.itsaky.inflater.values.models.ArrayResource;
-import com.itsaky.inflater.values.models.BooleanResource;
-import com.itsaky.inflater.values.models.ColorResource;
-import com.itsaky.inflater.values.models.DimensionResource;
-import com.itsaky.inflater.values.models.IntegerResource;
-import com.itsaky.inflater.values.models.StringResource;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Reads and manages values (colors, strings, integers, etc.) for a single module.
- *
- * @author Akash Yadav
- */
-public class ValuesTable {
-
- private static final ILogger LOG = ILogger.newInstance("ValuesTable");
- // TODO Parse styles and styleables
- private final Map arrays;
- private final Map strings;
- private final Map colors;
- private final Map integers;
- private final Map dimens;
- private final Map booleans;
-
- private final Map> resourceMap = new HashMap<>();
-
- protected ValuesTable() {
- this.arrays = new HashMap<>();
- this.strings = new HashMap<>();
- this.colors = new HashMap<>();
- this.integers = new HashMap<>();
- this.dimens = new HashMap<>();
- this.booleans = new HashMap<>();
-
- this.resourceMap.put("array", this.arrays);
- this.resourceMap.put("string", this.strings);
- this.resourceMap.put("color", this.colors);
- this.resourceMap.put("integer", this.integers);
- this.resourceMap.put("dimen", this.dimens);
- this.resourceMap.put("bool", this.booleans);
- }
-
- /**
- * Create a new table by reading the files from the given values directory.
- *
- * @param valuesDirectory The "res/values" directory.
- * @return The values table or {@code null} if the directory is invalid or there are no files in
- * this directory.
- * @throws XmlPullParserException Thrown by {@link XmlPullParserFactory}.
- * @throws IOException Thrown by {@link XmlPullParser}.
- */
- @Nullable
- public static ValuesTable forDirectory(File valuesDirectory) throws Exception {
- if (valuesDirectory == null) {
- LOG.error("Cannot create values table for directory: ", null);
- return null;
- }
-
- if (!valuesDirectory.exists()) {
- LOG.error(
- "Cannot create values table for directory as it does not exists. Directory:",
- valuesDirectory);
- return null;
- }
-
- final var files = valuesDirectory.listFiles(ValuesTable::isValid);
- if (files == null) {
- LOG.error("No files found in the given values directory");
- return null;
- }
-
- final var start = System.currentTimeMillis();
- final var values = new ValuesTable();
-
- for (var file : files) {
- final var factory = XmlPullParserFactory.newInstance();
- final var parser = factory.newPullParser();
- parser.setInput(new FileInputStream(file), null);
-
- var event = parser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final var tag = parser.getName();
- if ("resources".equals(tag)) {
- event = parser.next();
- continue;
- }
-
- readTag(tag, parser, values);
- }
- event = parser.next();
- }
- }
-
- final var duration = System.currentTimeMillis() - start;
- LOG.info(
- String.format(
- Locale.getDefault(),
- "Took %d ms to read %d files in directory: %s",
- duration,
- files.length,
- valuesDirectory));
-
- return values;
- }
-
- private static void readTag(String tag, XmlPullParser parser, ValuesTable values)
- throws Exception {
-
- if ("style".equals(tag) || "declare-styleable".equals(tag)) {
- // These tags are not supported yet
- // Skip parsing until we reach next tag with same depth as of this tag
- skip(parser);
- return;
- }
-
- // TODO Should we check if these tags are specified within ?
- final var name = getName(parser);
- if (name == null) {
- LOG.error(String.format("A <%s> resource was found with no 'name' attribute", tag));
- return;
- }
-
- if ("item".equals(tag)) {
- tag = parser.getAttributeValue(null, "type");
- if (tag == null) {
- LOG.error("- resource value found but no 'type' was specified.");
- return;
- }
- }
-
- // check for array before reading value
- // because array resources do not have text values
- if ("array".equals(tag) || tag.endsWith("-array")) {
- readArray(parser, values, name);
- return;
- }
-
- // Value must be read after all other required values have been read
- final var value = parser.nextText();
- IResource resourceValue;
-
- switch (tag) {
- case "string":
- resourceValue = new StringResource(name, value);
- values.strings.put(name, resourceValue);
- break;
- case "color":
- resourceValue = new ColorResource(name, value);
- values.colors.put(name, resourceValue);
- break;
- case "bool":
- resourceValue = new BooleanResource(name, value);
- values.booleans.put(name, resourceValue);
- break;
- case "dimen":
- resourceValue = new DimensionResource(name, value);
- values.dimens.put(name, resourceValue);
- break;
- case "integer":
- resourceValue = new IntegerResource(name, value);
- values.integers.put(name, resourceValue);
- break;
- default:
- LOG.warn("Unknown or unsupported resource value tag:", tag);
- break;
- }
- }
-
- private static void readArray(@NonNull XmlPullParser parser, ValuesTable values, String name)
- throws XmlPullParserException, IOException {
- final var minDepth = parser.getDepth();
- final var items = new ArrayList();
-
- var event = parser.getEventType();
- while ((event = parser.next()) != XmlPullParser.END_DOCUMENT && parser.getDepth() >= minDepth) {
- if (event == XmlPullParser.START_TAG) {
- final var child = parser.getName();
- if ("item".equals(child)) {
- final var value = parser.nextText();
- items.add(value);
- }
- }
- }
-
- final var arr = new String[items.size()];
- for (int i = 0; i < arr.length; i++) {
- arr[i] = items.get(i);
- }
-
- values.arrays.put(name, new ArrayResource(name, arr));
- }
-
- private static void skip(@NonNull XmlPullParser parser)
- throws XmlPullParserException, IOException {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- throw new IllegalStateException();
- }
- int depth = 1;
- while (depth != 0) {
- switch (parser.next()) {
- case XmlPullParser.END_TAG:
- depth--;
- break;
- case XmlPullParser.START_TAG:
- depth++;
- break;
- }
- }
- }
-
- private static String getName(@NonNull XmlPullParser parser) {
- return parser.getAttributeValue(null, "name");
- }
-
- private static boolean isValid(File file) {
- return file != null && file.isFile() && FileUtils.isUtf8(file);
- }
-
- @Nullable
- public Map getTable(final String name) {
- Objects.requireNonNull(name);
- return this.resourceMap.get(name);
- }
-
- @NonNull
- public Map> getResourceMap() {
- return resourceMap;
- }
-
- /**
- * Finds a resource value of any type.
- *
- * @param name The name of the resource to find.
- * @return The resource value or {@code null} if there is no resource with the given name.
- */
- @SuppressWarnings("unused")
- public IResource findResource(final String name) {
- IResource value;
-
- value = findString(name);
- if (value != null) {
- return value;
- }
-
- value = findColor(name);
- if (value != null) {
- return value;
- }
-
- value = findInteger(name);
- if (value != null) {
- return value;
- }
-
- value = findDimension(name);
- if (value != null) {
- return value;
- }
-
- value = findArray(name);
- if (value != null) {
- return value;
- }
-
- value = findBoolean(name);
- //noinspection RedundantIfStatement
- if (value != null) {
- return value;
- }
-
- return null;
- }
-
- public ArrayResource findArray(final String name) {
- return (ArrayResource) arrays.getOrDefault(name, null);
- }
-
- /**
- * Find a string value with the given name.
- *
- * @param name The name of the string resource.
- * @return The string resource or {@code null} if there is no resource with the given name.
- */
- public StringResource findString(final String name) {
- return (StringResource) strings.getOrDefault(name, null);
- }
-
- /**
- * Find a color value with the given name.
- *
- * @param name The name of the color resource.
- * @return The color resource or {@code null} if there is no resource with the given name.
- */
- public ColorResource findColor(final String name) {
- return (ColorResource) colors.getOrDefault(name, null);
- }
-
- /**
- * Find a integer value with the given name.
- *
- * @param name The name of the integer resource.
- * @return The integer resource or {@code null} if there is no resource with the given name.
- */
- public IntegerResource findInteger(final String name) {
- return (IntegerResource) integers.getOrDefault(name, null);
- }
-
- /**
- * Find a dimension value with the given name.
- *
- * @param name The name of the dimension resource.
- * @return The dimension resource or {@code null} if there is no resource with the given name.
- */
- public DimensionResource findDimension(final String name) {
- return (DimensionResource) dimens.getOrDefault(name, null);
- }
-
- /**
- * Find a boolean value with the given name.
- *
- * @param name The name of the boolean resource.
- * @return The boolean resource or {@code null} if there is no resource with the given name.
- */
- public BooleanResource findBoolean(final String name) {
- return (BooleanResource) booleans.getOrDefault(name, null);
- }
-
- /**
- * Reads the contents of the given file and updates this table.
- *
- * @param file The file to sync with.
- */
- public void syncWithFile(final File file) throws Exception {
- final var start = System.currentTimeMillis();
- final var factory = XmlPullParserFactory.newInstance();
- final var parser = factory.newPullParser();
- parser.setInput(new FileInputStream(file), null);
-
- var event = parser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- if (event == XmlPullParser.START_TAG) {
- final var tag = parser.getName();
- if ("resources".equals(tag)) {
- event = parser.next();
- continue;
- }
-
- ValuesTable.readTag(tag, parser, this);
- }
- event = parser.next();
- }
-
- LOG.debug(
- "Syncing with file", file.getName(), "took", (System.currentTimeMillis() - start), "ms");
- }
-
- @NonNull
- @Override
- public String toString() {
- return "ValuesTable{"
- + "strings="
- + strings
- + ", colors="
- + colors
- + ", integers="
- + integers
- + ", dimens="
- + dimens
- + ", booleans="
- + booleans
- + '}';
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java
deleted file mode 100644
index ebc1c5791..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTableFactory.java
+++ /dev/null
@@ -1,138 +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.inflater.values;
-
-import com.itsaky.androidide.utils.ILogger;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * A factory class that reads the files in the "values" directory of given "res" directories.
- *
- * @author Akash Yadav
- */
-public class ValuesTableFactory {
-
- private static final Map valueTables = new HashMap<>();
- private static final ILogger LOG = ILogger.newInstance("ValuesTableFactory");
-
- public static ValuesTable getTable(final File resDir) {
- return valueTables.getOrDefault(resDir, null);
- }
-
- public static Map getAllTables() {
- return valueTables;
- }
-
- /**
- * Setup this ValuesTableFactory with the given "res" directories.
- *
- * @param resDirs The resource directories.
- */
- public static void setupWithResDirectories(File... resDirs) {
-
- if (resDirs == null || resDirs.length <= 0) {
- LOG.error("Cannot create value tables. No directories were specified.");
- return;
- }
-
- valueTables.clear();
-
- final var start = System.currentTimeMillis();
- for (var res : resDirs) {
- if (res == null || !res.exists()) {
- continue;
- }
-
- final var table = createTable(res);
- if (table == null) {
- continue;
- }
-
- valueTables.put(res, table);
- }
-
- LOG.debug(
- String.format(
- Locale.getDefault(),
- "Created value tables for %d resource directories in %d ms",
- resDirs.length,
- (System.currentTimeMillis() - start)));
- }
-
- private static ValuesTable createTable(File res) {
- try {
- final var values = new File(res, "values");
- if (!values.exists()) {
- return null;
- }
-
- var table = ValuesTable.forDirectory(values);
- if (table == null) {
- throw new ParseException();
- }
-
- return table;
- } catch (Throwable e) {
- LOG.error("Failed to create values table", e);
- return null;
- }
- }
-
- /**
- * Notify that the given file's contents were changed and the corresponding table must be updated
- * with new values.
- *
- * @param file The file that was changed.
- */
- public static void syncWithFile(final File file) {
- if (file == null) {
- LOG.error("Cannot update value tables. Given file is null.");
- return;
- }
-
- final var pattern = Pattern.compile(".*/src/.*/res/values/(\\w|_)+\\.xml");
- if (!pattern.matcher(file.getAbsolutePath()).matches()) {
- // This file is not a values resource file.
- return;
- }
-
- final var resDir =
- Objects.requireNonNull(file.getParentFile()) /* values dir */.getParentFile() /* res dir*/;
- var table = valueTables.getOrDefault(resDir, null);
- if (table == null) {
- table = createTable(resDir);
- if (table != null) {
- valueTables.put(resDir, table);
- }
- return;
- }
-
- try {
- table.syncWithFile(file);
- } catch (Throwable e) {
- LOG.error("Failed to sync values table", e);
- }
- }
-
- static class ParseException extends RuntimeException {}
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java
deleted file mode 100644
index da5aea7c1..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/AbstractResource.java
+++ /dev/null
@@ -1,84 +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.inflater.values.models;
-
-import androidx.annotation.NonNull;
-
-import com.itsaky.inflater.values.IResource;
-
-import java.util.Objects;
-
-/**
- * Abstract class for resource value entries.
- *
- * @author Akash Yadav
- */
-abstract class AbstractResource implements IResource {
-
- private final String name;
- private final String value;
-
- public AbstractResource(@NonNull String name, @NonNull String value) {
- this.name = name;
- this.value = value;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getName(), getValue());
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof AbstractResource)) {
- return false;
- }
-
- AbstractResource that = (AbstractResource) o;
- return Objects.equals(getName(), that.getName()) && Objects.equals(getValue(), that.getValue());
- }
-
- @NonNull
- @Override
- public String getName() {
- return name;
- }
-
- @NonNull
- @Override
- public String getValue() {
- return value;
- }
-
- @NonNull
- @Override
- public String toString() {
- return getClass().getSimpleName()
- + "{"
- + "name='"
- + name
- + '\''
- + ", value='"
- + value
- + '\''
- + '}';
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ArrayResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ArrayResource.java
deleted file mode 100644
index 352c14c7d..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ArrayResource.java
+++ /dev/null
@@ -1,76 +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.inflater.values.models;
-
-import android.graphics.Color;
-import android.text.TextUtils;
-
-import androidx.annotation.NonNull;
-
-/**
- * An array resource. Can be any of the following :
- *
- *
- * - <integer-array>
- *
- <string-array>
- *
- <array>
- *
- *
- * @author Akash Yadav
- */
-public class ArrayResource extends AbstractResource {
-
- private final String[] values;
-
- public ArrayResource(@NonNull String name, @NonNull String[] values) {
- super(name, TextUtils.join(", ", values));
- this.values = values;
- }
-
- public String[] getValues() {
- return values;
- }
-
- public int[] getIntValues() {
- final var ints = new int[values.length];
- for (int i = 0; i < ints.length; i++) {
- var value = values[i];
- if (value == null || value.trim().length() == 0) {
- value = "0";
- }
-
- ints[i] = Integer.parseInt(value);
- }
-
- return ints;
- }
-
- public int[] getColorValues() {
- final var colors = new int[this.values.length];
- for (int i = 0; i < colors.length; i++) {
- var val = values[i];
- if (val == null || val.trim().length() == 0) {
- val = "#ffffff";
- }
-
- colors[i] = Color.parseColor(val);
- }
-
- return colors;
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java
deleted file mode 100644
index 9100ab820..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/BooleanResource.java
+++ /dev/null
@@ -1,49 +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.inflater.values.models;
-
-import androidx.annotation.NonNull;
-
-/**
- * @author Akash Yadav
- */
-public class BooleanResource extends AbstractResource {
-
- public BooleanResource(@NonNull String name, @NonNull String value) {
- super(name, value);
- }
-
- /**
- * Get the value of this resource as boolean.
- *
- * @return The value of this resource.
- * @throws UnsupportedOperationException If the value is not a boolean value. This will also be
- * thrown if the value this resource refers to another resource.
- */
- public boolean asBoolean() {
- final var val = getValue();
- switch (val) {
- case "true":
- return true;
- case "false":
- return false;
- default:
- throw new UnsupportedOperationException("Cannot parse boolean value: " + val);
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java
deleted file mode 100644
index 155b666a6..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/ColorResource.java
+++ /dev/null
@@ -1,46 +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.inflater.values.models;
-
-import android.graphics.Color;
-
-import androidx.annotation.NonNull;
-
-/**
- * Represents a color resource value.
- *
- * @author Akash Yadav
- */
-public class ColorResource extends AbstractResource {
-
- public ColorResource(@NonNull String name, @NonNull String value) {
- super(name, value);
- }
-
- /**
- * Parse the value of this color resource and get the int color.
- *
- * @return The int color value or -1 if this is not a valid color.
- */
- public int parseColor() {
- try {
- return Color.parseColor(getValue());
- } catch (Throwable th) {
- return -1;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java
deleted file mode 100644
index 2e12cc460..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/IntegerResource.java
+++ /dev/null
@@ -1,44 +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.inflater.values.models;
-
-import androidx.annotation.NonNull;
-
-/**
- * Represents an integer value.
- *
- * @author Akash Yadav
- */
-public class IntegerResource extends AbstractResource {
-
- public IntegerResource(@NonNull String name, @NonNull String value) {
- super(name, value);
- }
-
- /**
- * Get the value as integer. Or -1 if the value is not an integer.
- *
- * @return The integer value.
- */
- public int asInteger() {
- try {
- return Integer.parseInt(getValue());
- } catch (Throwable th) {
- return -1;
- }
- }
-}
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java
deleted file mode 100644
index 2385f825b..000000000
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/models/StringResource.java
+++ /dev/null
@@ -1,31 +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.inflater.values.models;
-
-import androidx.annotation.NonNull;
-
-/**
- * Represents a string value.
- *
- * @author Akash Yadav
- */
-public class StringResource extends AbstractResource {
-
- public StringResource(@NonNull String name, @NonNull String value) {
- super(name, value);
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/DefaultValues.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/DefaultValues.java
deleted file mode 100644
index 9e051f6e5..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/DefaultValues.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.sdsmdg.harjot.vectormaster;
-
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-
-public class DefaultValues {
-
- public static final int PATH_FILL_COLOR = Color.TRANSPARENT;
- public static final int PATH_STROKE_COLOR = Color.TRANSPARENT;
- public static final float PATH_STROKE_WIDTH = 0.0f;
- public static final float PATH_STROKE_ALPHA = 1.0f;
- public static final float PATH_FILL_ALPHA = 1.0f;
- public static final Paint.Cap PATH_STROKE_LINE_CAP = Paint.Cap.BUTT;
- public static final Paint.Join PATH_STROKE_LINE_JOIN = Paint.Join.MITER;
- public static final float PATH_STROKE_MITER_LIMIT = 4.0f;
- public static final float PATH_STROKE_RATIO = 1.0f;
- // WINDING fill type is equivalent to NON_ZERO
- public static final Path.FillType PATH_FILL_TYPE = Path.FillType.WINDING;
- public static final float PATH_TRIM_PATH_START = 0.0f;
- public static final float PATH_TRIM_PATH_END = 1.0f;
- public static final float PATH_TRIM_PATH_OFFSET = 0.0f;
- public static final float VECTOR_VIEWPORT_WIDTH = 0.0f;
- public static final float VECTOR_VIEWPORT_HEIGHT = 0.0f;
- public static final float VECTOR_WIDTH = 0.0f;
- public static final float VECTOR_HEIGHT = 0.0f;
- public static final float VECTOR_ALPHA = 1.0f;
- public static final float GROUP_ROTATION = 0.0f;
- public static final float GROUP_PIVOT_X = 0.0f;
- public static final float GROUP_PIVOT_Y = 0.0f;
- public static final float GROUP_SCALE_X = 1.0f;
- public static final float GROUP_SCALE_Y = 1.0f;
- public static final float GROUP_TRANSLATE_X = 0.0f;
- public static final float GROUP_TRANSLATE_Y = 0.0f;
- public static String[] PATH_ATTRIBUTES = {
- "name",
- "fillAlpha",
- "fillColor",
- "fillType",
- "pathData",
- "strokeAlpha",
- "strokeColor",
- "strokeLineCap",
- "strokeLineJoin",
- "strokeMiterLimit",
- "strokeWidth"
- };
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java
deleted file mode 100644
index 91aa56bbe..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterDrawable.java
+++ /dev/null
@@ -1,564 +0,0 @@
-package com.sdsmdg.harjot.vectormaster;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Matrix;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-import androidx.annotation.NonNull;
-
-import com.blankj.utilcode.util.FileIOUtils;
-import com.sdsmdg.harjot.vectormaster.models.ClipPathModel;
-import com.sdsmdg.harjot.vectormaster.models.GroupModel;
-import com.sdsmdg.harjot.vectormaster.models.PathModel;
-import com.sdsmdg.harjot.vectormaster.models.VectorModel;
-import com.sdsmdg.harjot.vectormaster.utilities.Utils;
-
-import org.jetbrains.annotations.Contract;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Stack;
-
-public class VectorMasterDrawable extends Drawable {
-
- private VectorModel vectorModel;
-
- private int resID = -1;
- private boolean useLegacyParser = true;
-
- private float offsetX = 0.0f, offsetY = 0.0f;
- private float scaleX = 1.0f, scaleY = 1.0f;
- private Matrix scaleMatrix;
-
- private float scaleRatio, strokeRatio;
- private int width = -1, height = -1;
- private int left = 0, top = 0;
- private XmlPullParser xpp;
-
- public VectorMasterDrawable(Context context, int resID) {
- this(context, resID, 0.0f, 0.0f);
- }
-
- public VectorMasterDrawable(Context context, int resID, float offsetX, float offsetY) {
- this(context, resID, offsetX, offsetY, 1.0f, 1.0f);
- }
-
- public VectorMasterDrawable(
- @NonNull Context context,
- int resID,
- float offsetX,
- float offsetY,
- float scaleX,
- float scaleY) {
- this.resID = resID;
- this.offsetX = offsetX;
- this.offsetY = offsetY;
- this.scaleX = scaleX;
- this.scaleY = scaleY;
-
- final var resources = context.getResources();
-
- if (resID == -1) {
- vectorModel = null;
- return;
- }
-
- this.xpp = resources.getXml(resID);
- buildVectorModel();
- }
-
- private void buildVectorModel() {
- int tempPosition;
- PathModel pathModel = new PathModel();
- vectorModel = new VectorModel();
- GroupModel groupModel = new GroupModel();
- ClipPathModel clipPathModel = new ClipPathModel();
- Stack groupModelStack = new Stack<>();
-
- try {
- int event = xpp.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- String name = xpp.getName();
- switch (event) {
- case XmlPullParser.START_TAG:
- switch (name) {
- case "vector":
- tempPosition = getAttrPosition(xpp, "viewportWidth");
- vectorModel.setViewportWidth(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_VIEWPORT_WIDTH);
-
- tempPosition = getAttrPosition(xpp, "viewportHeight");
- vectorModel.setViewportHeight(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_VIEWPORT_HEIGHT);
-
- tempPosition = getAttrPosition(xpp, "alpha");
- vectorModel.setAlpha(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_ALPHA);
-
- tempPosition = getAttrPosition(xpp, "name");
- vectorModel.setName(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "width");
- vectorModel.setWidth(
- (tempPosition != -1)
- ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_WIDTH);
-
- tempPosition = getAttrPosition(xpp, "height");
- vectorModel.setHeight(
- (tempPosition != -1)
- ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_HEIGHT);
- break;
- case "path":
- pathModel = new PathModel();
-
- tempPosition = getAttrPosition(xpp, "name");
- pathModel.setName(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "fillAlpha");
- pathModel.setFillAlpha(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_FILL_ALPHA);
-
- tempPosition = getAttrPosition(xpp, "fillColor");
- pathModel.setFillColor(
- (tempPosition != -1)
- ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_FILL_COLOR);
-
- tempPosition = getAttrPosition(xpp, "fillType");
- pathModel.setFillType(
- (tempPosition != -1)
- ? Utils.getFillTypeFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_FILL_TYPE);
-
- tempPosition = getAttrPosition(xpp, "pathData");
- pathModel.setPathData(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "strokeAlpha");
- pathModel.setStrokeAlpha(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_ALPHA);
-
- tempPosition = getAttrPosition(xpp, "strokeColor");
- pathModel.setStrokeColor(
- (tempPosition != -1)
- ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_COLOR);
-
- tempPosition = getAttrPosition(xpp, "strokeLineCap");
- pathModel.setStrokeLineCap(
- (tempPosition != -1)
- ? Utils.getLineCapFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_LINE_CAP);
-
- tempPosition = getAttrPosition(xpp, "strokeLineJoin");
- pathModel.setStrokeLineJoin(
- (tempPosition != -1)
- ? Utils.getLineJoinFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_LINE_JOIN);
-
- tempPosition = getAttrPosition(xpp, "strokeMiterLimit");
- pathModel.setStrokeMiterLimit(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_MITER_LIMIT);
-
- tempPosition = getAttrPosition(xpp, "strokeWidth");
- pathModel.setStrokeWidth(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_WIDTH);
-
- tempPosition = getAttrPosition(xpp, "trimPathEnd");
- pathModel.setTrimPathEnd(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_TRIM_PATH_END);
-
- tempPosition = getAttrPosition(xpp, "trimPathOffset");
- pathModel.setTrimPathOffset(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_TRIM_PATH_OFFSET);
-
- tempPosition = getAttrPosition(xpp, "trimPathStart");
- pathModel.setTrimPathStart(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_TRIM_PATH_START);
-
- pathModel.buildPath(useLegacyParser);
- break;
- case "group":
- groupModel = new GroupModel();
-
- tempPosition = getAttrPosition(xpp, "name");
- groupModel.setName(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "pivotX");
- groupModel.setPivotX(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_PIVOT_X);
-
- tempPosition = getAttrPosition(xpp, "pivotY");
- groupModel.setPivotY(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_PIVOT_Y);
-
- tempPosition = getAttrPosition(xpp, "rotation");
- groupModel.setRotation(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_ROTATION);
-
- tempPosition = getAttrPosition(xpp, "scaleX");
- groupModel.setScaleX(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_SCALE_X);
-
- tempPosition = getAttrPosition(xpp, "scaleY");
- groupModel.setScaleY(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_SCALE_Y);
-
- tempPosition = getAttrPosition(xpp, "translateX");
- groupModel.setTranslateX(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_TRANSLATE_X);
-
- tempPosition = getAttrPosition(xpp, "translateY");
- groupModel.setTranslateY(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_TRANSLATE_Y);
-
- groupModelStack.push(groupModel);
- break;
- case "clip-path":
- clipPathModel = new ClipPathModel();
-
- tempPosition = getAttrPosition(xpp, "name");
- clipPathModel.setName(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "pathData");
- clipPathModel.setPathData(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- clipPathModel.buildPath(useLegacyParser);
- break;
- }
- break;
-
- case XmlPullParser.END_TAG:
- switch (name) {
- case "path":
- if (groupModelStack.size() == 0) {
- vectorModel.addPathModel(pathModel);
- } else {
- groupModelStack.peek().addPathModel(pathModel);
- }
- vectorModel.getFullpath().addPath(pathModel.getPath());
- break;
- case "clip-path":
- if (groupModelStack.size() == 0) {
- vectorModel.addClipPathModel(clipPathModel);
- } else {
- groupModelStack.peek().addClipPathModel(clipPathModel);
- }
- break;
- case "group":
- GroupModel topGroupModel = groupModelStack.pop();
- if (groupModelStack.size() == 0) {
- topGroupModel.setParent(null);
- vectorModel.addGroupModel(topGroupModel);
- } else {
- topGroupModel.setParent(groupModelStack.peek());
- groupModelStack.peek().addGroupModel(topGroupModel);
- }
- break;
- case "vector":
- vectorModel.buildTransformMatrices();
- break;
- }
- break;
- }
- event = xpp.next();
- }
- } catch (XmlPullParserException | IOException e) {
- e.printStackTrace();
- }
- }
-
- private int getAttrPosition(@NonNull XmlPullParser xpp, String attrName) {
- for (int i = 0; i < xpp.getAttributeCount(); i++) {
- if (xpp.getAttributeName(i).equals(attrName)) {
- return i;
- }
- }
- return -1;
- }
-
- public VectorMasterDrawable(XmlPullParser parser) {
- this.xpp = parser;
- buildVectorModel();
- }
-
- @NonNull
- public static VectorMasterDrawable fromXMLFile(File file) throws XmlPullParserException {
- final var source = FileIOUtils.readFile2String(file);
- return VectorMasterDrawable.fromXML(source);
- }
-
- @NonNull
- @Contract("_ -> new")
- public static VectorMasterDrawable fromXML(@NonNull String vectorXML)
- throws XmlPullParserException {
- final var factory = XmlPullParserFactory.newInstance();
- factory.setNamespaceAware(true);
-
- final var parser = factory.newPullParser();
- parser.setInput(new StringReader(vectorXML));
- return new VectorMasterDrawable(parser);
- }
-
- public int getResID() {
- return resID;
- }
-
- public void setResID(int resID) {
- this.resID = resID;
- buildVectorModel();
- scaleMatrix = null;
- }
-
- public boolean isUseLegacyParser() {
- return useLegacyParser;
- }
-
- public void setUseLegacyParser(boolean useLegacyParser) {
- this.useLegacyParser = useLegacyParser;
- buildVectorModel();
- scaleMatrix = null;
- }
-
- @Override
- public void draw(Canvas canvas) {
-
- if (vectorModel == null) {
- return;
- }
-
- if (scaleMatrix == null) {
- int temp1 = Utils.dpToPx((int) vectorModel.getWidth());
- int temp2 = Utils.dpToPx((int) vectorModel.getHeight());
-
- setBounds(0, 0, temp1, temp2);
- }
-
- setAlpha(Utils.getAlphaFromFloat(vectorModel.getAlpha()));
-
- if (left != 0 || top != 0) {
- int tempSaveCount = canvas.save();
- canvas.translate(left, top);
- vectorModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY);
- canvas.restoreToCount(tempSaveCount);
- } else {
- vectorModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY);
- }
- }
-
- @Override
- public void setAlpha(int i) {
- vectorModel.setAlpha(Utils.getAlphaFromInt(i));
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {}
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
-
- if (bounds.width() != 0 && bounds.height() != 0) {
-
- left = bounds.left;
- top = bounds.top;
-
- width = bounds.width();
- height = bounds.height();
-
- buildScaleMatrix();
- scaleAllPaths();
- scaleAllStrokes();
- }
- }
-
- @Override
- public int getIntrinsicWidth() {
- return Utils.dpToPx((int) vectorModel.getWidth());
- }
-
- @Override
- public int getIntrinsicHeight() {
- return Utils.dpToPx((int) vectorModel.getHeight());
- }
-
- private void buildScaleMatrix() {
- scaleMatrix = new Matrix();
-
- scaleMatrix.postTranslate(
- width / 2 - vectorModel.getViewportWidth() / 2,
- height / 2 - vectorModel.getViewportHeight() / 2);
-
- float widthRatio = width / vectorModel.getViewportWidth();
- float heightRatio = height / vectorModel.getViewportHeight();
- float ratio = Math.min(widthRatio, heightRatio);
-
- scaleRatio = ratio;
-
- scaleMatrix.postScale(ratio, ratio, width / 2, height / 2);
- }
-
- private void scaleAllPaths() {
- vectorModel.scaleAllPaths(scaleMatrix);
- }
-
- private void scaleAllStrokes() {
- strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight());
- vectorModel.scaleAllStrokeWidth(strokeRatio);
- }
-
- public Path getFullPath() {
- if (vectorModel != null) {
- return vectorModel.getFullpath();
- }
- return null;
- }
-
- public GroupModel getGroupModelByName(String name) {
- GroupModel gModel;
- for (GroupModel groupModel : vectorModel.getGroupModels()) {
- if (Utils.isEqual(groupModel.getName(), name)) {
- return groupModel;
- } else {
- gModel = groupModel.getGroupModelByName(name);
- if (gModel != null) return gModel;
- }
- }
- return null;
- }
-
- public PathModel getPathModelByName(String name) {
- PathModel pModel = null;
- for (PathModel pathModel : vectorModel.getPathModels()) {
- if (Utils.isEqual(pathModel.getName(), name)) {
- return pathModel;
- }
- }
- for (GroupModel groupModel : vectorModel.getGroupModels()) {
- pModel = groupModel.getPathModelByName(name);
- if (pModel != null && Utils.isEqual(pModel.getName(), name)) return pModel;
- }
- return pModel;
- }
-
- public ClipPathModel getClipPathModelByName(String name) {
- ClipPathModel cModel = null;
- for (ClipPathModel clipPathModel : vectorModel.getClipPathModels()) {
- if (Utils.isEqual(clipPathModel.getName(), name)) {
- return clipPathModel;
- }
- }
- for (GroupModel groupModel : vectorModel.getGroupModels()) {
- cModel = groupModel.getClipPathModelByName(name);
- if (cModel != null && Utils.isEqual(cModel.getName(), name)) return cModel;
- }
- return cModel;
- }
-
- public void update() {
- invalidateSelf();
- }
-
- public float getScaleRatio() {
- return scaleRatio;
- }
-
- public float getStrokeRatio() {
- return strokeRatio;
- }
-
- public Matrix getScaleMatrix() {
- return scaleMatrix;
- }
-
- public float getOffsetX() {
- return offsetX;
- }
-
- public void setOffsetX(float offsetX) {
- this.offsetX = offsetX;
- invalidateSelf();
- }
-
- public float getOffsetY() {
- return offsetY;
- }
-
- public void setOffsetY(float offsetY) {
- this.offsetY = offsetY;
- invalidateSelf();
- }
-
- public float getScaleX() {
- return scaleX;
- }
-
- public void setScaleX(float scaleX) {
- this.scaleX = scaleX;
- invalidateSelf();
- }
-
- public float getScaleY() {
- return scaleY;
- }
-
- public void setScaleY(float scaleY) {
- this.scaleY = scaleY;
- invalidateSelf();
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java
deleted file mode 100644
index 1d8e42daf..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/VectorMasterView.java
+++ /dev/null
@@ -1,447 +0,0 @@
-package com.sdsmdg.harjot.vectormaster;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Path;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.itsaky.androidide.resources.R;
-import com.sdsmdg.harjot.vectormaster.models.ClipPathModel;
-import com.sdsmdg.harjot.vectormaster.models.GroupModel;
-import com.sdsmdg.harjot.vectormaster.models.PathModel;
-import com.sdsmdg.harjot.vectormaster.models.VectorModel;
-import com.sdsmdg.harjot.vectormaster.utilities.Utils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Stack;
-
-public class VectorMasterView extends View {
-
- private Matrix scaleMatrix;
- private float scaleRatio, strokeRatio;
- VectorModel vectorModel;
- Context context;
- Resources resources;
- int resID = -1;
- boolean useLegacyParser = true;
- XmlPullParser xpp;
- int width = 0, height = 0;
-
- public VectorMasterView(Context context) {
- super(context);
- this.context = context;
- }
-
- public VectorMasterView(Context context, AttributeSet attrs) {
- super(context, attrs);
- this.context = context;
- init(attrs);
- }
-
- void init(AttributeSet attrs) {
- resources = context.getResources();
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VectorMasterView);
- final int N = a.getIndexCount();
- for (int i = 0; i < N; ++i) {
- int attr = a.getIndex(i);
- if (attr == R.styleable.VectorMasterView_vector_src) {
- resID = a.getResourceId(attr, -1);
- } else if (attr == R.styleable.VectorMasterView_use_legacy_parser) {
- useLegacyParser = a.getBoolean(attr, false);
- }
- }
- a.recycle();
-
- buildVectorModel();
- }
-
- void buildVectorModel() {
-
- if (resID == -1) {
- vectorModel = null;
- return;
- }
-
- xpp = resources.getXml(resID);
-
- int tempPosition;
- PathModel pathModel = new PathModel();
- vectorModel = new VectorModel();
- GroupModel groupModel = new GroupModel();
- ClipPathModel clipPathModel = new ClipPathModel();
- Stack groupModelStack = new Stack<>();
-
- try {
- int event = xpp.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- String name = xpp.getName();
- switch (event) {
- case XmlPullParser.START_TAG:
- if (name.equals("vector")) {
- tempPosition = getAttrPosition(xpp, "viewportWidth");
- vectorModel.setViewportWidth(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_VIEWPORT_WIDTH);
-
- tempPosition = getAttrPosition(xpp, "viewportHeight");
- vectorModel.setViewportHeight(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_VIEWPORT_HEIGHT);
-
- tempPosition = getAttrPosition(xpp, "alpha");
- vectorModel.setAlpha(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_ALPHA);
-
- tempPosition = getAttrPosition(xpp, "name");
- vectorModel.setName(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "width");
- vectorModel.setWidth(
- (tempPosition != -1)
- ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_WIDTH);
-
- tempPosition = getAttrPosition(xpp, "height");
- vectorModel.setHeight(
- (tempPosition != -1)
- ? Utils.getFloatFromDimensionString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.VECTOR_HEIGHT);
- } else if (name.equals("path")) {
- pathModel = new PathModel();
-
- tempPosition = getAttrPosition(xpp, "name");
- pathModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "fillAlpha");
- pathModel.setFillAlpha(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_FILL_ALPHA);
-
- tempPosition = getAttrPosition(xpp, "fillColor");
- pathModel.setFillColor(
- (tempPosition != -1)
- ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_FILL_COLOR);
-
- tempPosition = getAttrPosition(xpp, "fillType");
- pathModel.setFillType(
- (tempPosition != -1)
- ? Utils.getFillTypeFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_FILL_TYPE);
-
- tempPosition = getAttrPosition(xpp, "pathData");
- pathModel.setPathData(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "strokeAlpha");
- pathModel.setStrokeAlpha(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_ALPHA);
-
- tempPosition = getAttrPosition(xpp, "strokeColor");
- pathModel.setStrokeColor(
- (tempPosition != -1)
- ? Utils.getColorFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_COLOR);
-
- tempPosition = getAttrPosition(xpp, "strokeLineCap");
- pathModel.setStrokeLineCap(
- (tempPosition != -1)
- ? Utils.getLineCapFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_LINE_CAP);
-
- tempPosition = getAttrPosition(xpp, "strokeLineJoin");
- pathModel.setStrokeLineJoin(
- (tempPosition != -1)
- ? Utils.getLineJoinFromString(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_LINE_JOIN);
-
- tempPosition = getAttrPosition(xpp, "strokeMiterLimit");
- pathModel.setStrokeMiterLimit(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_MITER_LIMIT);
-
- tempPosition = getAttrPosition(xpp, "strokeWidth");
- pathModel.setStrokeWidth(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_STROKE_WIDTH);
-
- tempPosition = getAttrPosition(xpp, "trimPathEnd");
- pathModel.setTrimPathEnd(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_TRIM_PATH_END);
-
- tempPosition = getAttrPosition(xpp, "trimPathOffset");
- pathModel.setTrimPathOffset(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_TRIM_PATH_OFFSET);
-
- tempPosition = getAttrPosition(xpp, "trimPathStart");
- pathModel.setTrimPathStart(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.PATH_TRIM_PATH_START);
-
- pathModel.buildPath(useLegacyParser);
- } else if (name.equals("group")) {
- groupModel = new GroupModel();
-
- tempPosition = getAttrPosition(xpp, "name");
- groupModel.setName((tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "pivotX");
- groupModel.setPivotX(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_PIVOT_X);
-
- tempPosition = getAttrPosition(xpp, "pivotY");
- groupModel.setPivotY(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_PIVOT_Y);
-
- tempPosition = getAttrPosition(xpp, "rotation");
- groupModel.setRotation(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_ROTATION);
-
- tempPosition = getAttrPosition(xpp, "scaleX");
- groupModel.setScaleX(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_SCALE_X);
-
- tempPosition = getAttrPosition(xpp, "scaleY");
- groupModel.setScaleY(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_SCALE_Y);
-
- tempPosition = getAttrPosition(xpp, "translateX");
- groupModel.setTranslateX(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_TRANSLATE_X);
-
- tempPosition = getAttrPosition(xpp, "translateY");
- groupModel.setTranslateY(
- (tempPosition != -1)
- ? Float.parseFloat(xpp.getAttributeValue(tempPosition))
- : DefaultValues.GROUP_TRANSLATE_Y);
-
- groupModelStack.push(groupModel);
- } else if (name.equals("clip-path")) {
- clipPathModel = new ClipPathModel();
-
- tempPosition = getAttrPosition(xpp, "name");
- clipPathModel.setName(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- tempPosition = getAttrPosition(xpp, "pathData");
- clipPathModel.setPathData(
- (tempPosition != -1) ? xpp.getAttributeValue(tempPosition) : null);
-
- clipPathModel.buildPath(useLegacyParser);
- }
- break;
-
- case XmlPullParser.END_TAG:
- if (name.equals("path")) {
- if (groupModelStack.size() == 0) {
- vectorModel.addPathModel(pathModel);
- } else {
- groupModelStack.peek().addPathModel(pathModel);
- }
- vectorModel.getFullpath().addPath(pathModel.getPath());
- } else if (name.equals("clip-path")) {
- if (groupModelStack.size() == 0) {
- vectorModel.addClipPathModel(clipPathModel);
- } else {
- groupModelStack.peek().addClipPathModel(clipPathModel);
- }
- } else if (name.equals("group")) {
- GroupModel topGroupModel = groupModelStack.pop();
- if (groupModelStack.size() == 0) {
- topGroupModel.setParent(null);
- vectorModel.addGroupModel(topGroupModel);
- } else {
- topGroupModel.setParent(groupModelStack.peek());
- groupModelStack.peek().addGroupModel(topGroupModel);
- }
- } else if (name.equals("vector")) {
- vectorModel.buildTransformMatrices();
- }
- break;
- }
- event = xpp.next();
- }
- } catch (XmlPullParserException | IOException e) {
- e.printStackTrace();
- }
- }
-
- int getAttrPosition(XmlPullParser xpp, String attrName) {
- for (int i = 0; i < xpp.getAttributeCount(); i++) {
- if (xpp.getAttributeName(i).equals(attrName)) {
- return i;
- }
- }
- return -1;
- }
-
- public VectorMasterView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- this.context = context;
- init(attrs);
- }
-
- public int getResID() {
- return resID;
- }
-
- public void setResID(int resID) {
- this.resID = resID;
- }
-
- public Path getFullPath() {
- if (vectorModel != null) {
- return vectorModel.getFullpath();
- }
- return null;
- }
-
- public GroupModel getGroupModelByName(String name) {
- GroupModel gModel;
- for (GroupModel groupModel : vectorModel.getGroupModels()) {
- if (Utils.isEqual(groupModel.getName(), name)) {
- return groupModel;
- } else {
- gModel = groupModel.getGroupModelByName(name);
- if (gModel != null) return gModel;
- }
- }
- return null;
- }
-
- public PathModel getPathModelByName(String name) {
- PathModel pModel = null;
- for (PathModel pathModel : vectorModel.getPathModels()) {
- if (Utils.isEqual(pathModel.getName(), name)) {
- return pathModel;
- }
- }
- for (GroupModel groupModel : vectorModel.getGroupModels()) {
- pModel = groupModel.getPathModelByName(name);
- if (pModel != null && Utils.isEqual(pModel.getName(), name)) return pModel;
- }
- return pModel;
- }
-
- public ClipPathModel getClipPathModelByName(String name) {
- ClipPathModel cModel = null;
- for (ClipPathModel clipPathModel : vectorModel.getClipPathModels()) {
- if (Utils.isEqual(clipPathModel.getName(), name)) {
- return clipPathModel;
- }
- }
- for (GroupModel groupModel : vectorModel.getGroupModels()) {
- cModel = groupModel.getClipPathModelByName(name);
- if (cModel != null && Utils.isEqual(cModel.getName(), name)) return cModel;
- }
- return cModel;
- }
-
- public void update() {
- invalidate();
- }
-
- public float getScaleRatio() {
- return scaleRatio;
- }
-
- public float getStrokeRatio() {
- return strokeRatio;
- }
-
- public Matrix getScaleMatrix() {
- return scaleMatrix;
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- if (w != 0 && h != 0) {
- width = w;
- height = h;
-
- buildScaleMatrix();
- scaleAllPaths();
- scaleAllStrokes();
- }
- }
-
- @SuppressLint("CanvasSize")
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- width = canvas.getWidth();
- height = canvas.getHeight();
-
- if (vectorModel == null) {
- return;
- }
-
- setAlpha(vectorModel.getAlpha());
-
- vectorModel.drawPaths(canvas);
- }
-
- void buildScaleMatrix() {
-
- scaleMatrix = new Matrix();
-
- scaleMatrix.postTranslate(
- width / 2 - vectorModel.getViewportWidth() / 2,
- height / 2 - vectorModel.getViewportHeight() / 2);
-
- float widthRatio = width / vectorModel.getViewportWidth();
- float heightRatio = height / vectorModel.getViewportHeight();
- float ratio = Math.min(widthRatio, heightRatio);
-
- scaleRatio = ratio;
-
- scaleMatrix.postScale(ratio, ratio, width / 2, height / 2);
- }
-
- void scaleAllPaths() {
- vectorModel.scaleAllPaths(scaleMatrix);
- }
-
- void scaleAllStrokes() {
- strokeRatio = Math.min(width / vectorModel.getWidth(), height / vectorModel.getHeight());
- vectorModel.scaleAllStrokeWidth(strokeRatio);
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/enums/TintMode.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/enums/TintMode.java
deleted file mode 100644
index 4742c74ca..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/enums/TintMode.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.enums;
-
-/** Created by Harjot on 20-Jun-17. */
-public enum TintMode {
- ADD,
- MULTIPLY,
- SCREEN,
- SRC_ATOP,
- SCR_IN,
- SRC_OVER
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java
deleted file mode 100644
index c2eedb868..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/ClipPathModel.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.models;
-
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.RectF;
-
-import com.sdsmdg.harjot.vectormaster.utilities.parser.PathParser;
-
-public class ClipPathModel {
- private String name;
- private String pathData;
-
- private Path originalPath;
- private Path path;
-
- private Paint clipPaint;
-
- public ClipPathModel() {
- path = new Path();
-
- clipPaint = new Paint();
- clipPaint.setAntiAlias(true);
- clipPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
- }
-
- public void buildPath(boolean useLegacyParser) {
- if (useLegacyParser) {
- originalPath =
- com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(
- pathData);
- } else {
- originalPath = PathParser.doPath(pathData);
- }
-
- path = new Path(originalPath);
- }
-
- public void transform(Matrix matrix) {
- path = new Path(originalPath);
-
- path.transform(matrix);
- }
-
- public Paint getClipPaint() {
- return clipPaint;
- }
-
- public void setClipPaint(Paint clipPaint) {
- this.clipPaint = clipPaint;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getPathData() {
- return pathData;
- }
-
- public void setPathData(String pathData) {
- this.pathData = pathData;
- }
-
- public Path getPath() {
- return path;
- }
-
- public void setPath(Path path) {
- this.path = path;
- }
-
- public Path getScaledAndOffsetPath(float offsetX, float offsetY, float scaleX, float scaleY) {
- Path newPath = new Path(path);
- newPath.offset(offsetX, offsetY);
- newPath.transform(getScaleMatrix(newPath, scaleX, scaleY));
- return newPath;
- }
-
- public Matrix getScaleMatrix(Path srcPath, float scaleX, float scaleY) {
- Matrix scaleMatrix = new Matrix();
- RectF rectF = new RectF();
- srcPath.computeBounds(rectF, true);
- scaleMatrix.setScale(scaleX, scaleY, rectF.left, rectF.top);
- return scaleMatrix;
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java
deleted file mode 100644
index 1441491fc..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/GroupModel.java
+++ /dev/null
@@ -1,280 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.models;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-
-import com.sdsmdg.harjot.vectormaster.DefaultValues;
-import com.sdsmdg.harjot.vectormaster.utilities.Utils;
-
-import java.util.ArrayList;
-
-public class GroupModel {
- private String name;
-
- private float rotation;
- private float pivotX, pivotY;
- private float scaleX, scaleY;
- private float translateX, translateY;
-
- private Matrix scaleMatrix;
- private Matrix originalTransformMatrix;
- private Matrix finalTransformMatrix;
- private GroupModel parent;
-
- private ArrayList groupModels;
- private ArrayList pathModels;
- private ArrayList clipPathModels;
-
- public GroupModel() {
- rotation = DefaultValues.GROUP_ROTATION;
- pivotX = DefaultValues.GROUP_PIVOT_X;
- pivotY = DefaultValues.GROUP_PIVOT_Y;
- scaleX = DefaultValues.GROUP_SCALE_X;
- scaleY = DefaultValues.GROUP_SCALE_Y;
- translateX = DefaultValues.GROUP_TRANSLATE_X;
- translateY = DefaultValues.GROUP_TRANSLATE_Y;
-
- groupModels = new ArrayList<>();
- pathModels = new ArrayList<>();
- clipPathModels = new ArrayList<>();
- }
-
- public void drawPaths(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) {
- for (ClipPathModel clipPathModel : clipPathModels) {
- canvas.clipPath(clipPathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY));
- }
- for (GroupModel groupModel : groupModels) {
- groupModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY);
- }
- for (PathModel pathModel : pathModels) {
- if (pathModel.isFillAndStroke()) {
- pathModel.makeFillPaint();
- canvas.drawPath(
- pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY),
- pathModel.getPathPaint());
- pathModel.makeStrokePaint();
- canvas.drawPath(
- pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY),
- pathModel.getPathPaint());
- } else {
- canvas.drawPath(
- pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY),
- pathModel.getPathPaint());
- }
- }
- }
-
- public void drawPaths(Canvas canvas) {
- for (ClipPathModel clipPathModel : clipPathModels) {
- canvas.clipPath(clipPathModel.getPath());
- }
- for (GroupModel groupModel : groupModels) {
- groupModel.drawPaths(canvas);
- }
- for (PathModel pathModel : pathModels) {
- if (pathModel.isFillAndStroke()) {
- pathModel.makeFillPaint();
- canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint());
- pathModel.makeStrokePaint();
- canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint());
- } else {
- canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint());
- }
- }
- }
-
- public void scaleAllPaths(Matrix scaleMatrix) {
- this.scaleMatrix = scaleMatrix;
- finalTransformMatrix = new Matrix(originalTransformMatrix);
- finalTransformMatrix.postConcat(scaleMatrix);
- for (GroupModel groupModel : groupModels) {
- groupModel.scaleAllPaths(scaleMatrix);
- }
- for (PathModel pathModel : pathModels) {
- pathModel.transform(finalTransformMatrix);
- }
- for (ClipPathModel clipPathModel : clipPathModels) {
- clipPathModel.transform(finalTransformMatrix);
- }
- }
-
- public void scaleAllStrokeWidth(float ratio) {
- for (GroupModel groupModel : groupModels) {
- groupModel.scaleAllStrokeWidth(ratio);
- }
- for (PathModel pathModel : pathModels) {
- pathModel.setStrokeRatio(ratio);
- }
- }
-
- public void buildTransformMatrix() {
-
- originalTransformMatrix = new Matrix();
-
- originalTransformMatrix.postScale(scaleX, scaleY, pivotX, pivotY);
- originalTransformMatrix.postRotate(rotation, pivotX, pivotY);
- originalTransformMatrix.postTranslate(translateX, translateY);
-
- if (parent != null) {
- originalTransformMatrix.postConcat(parent.getOriginalTransformMatrix());
- }
-
- for (GroupModel groupModel : groupModels) {
- groupModel.buildTransformMatrix();
- }
- }
-
- public void updateAndScalePaths() {
- if (scaleMatrix != null) {
- buildTransformMatrix();
- scaleAllPaths(scaleMatrix);
- }
- }
-
- public GroupModel getGroupModelByName(String name) {
- GroupModel grpModel = null;
- for (GroupModel groupModel : groupModels) {
- if (Utils.isEqual(groupModel.getName(), name)) {
- grpModel = groupModel;
- return grpModel;
- } else {
- grpModel = groupModel.getGroupModelByName(name);
- if (grpModel != null) return grpModel;
- }
- }
- return grpModel;
- }
-
- public PathModel getPathModelByName(String name) {
- PathModel pModel = null;
- for (PathModel pathModel : pathModels) {
- if (Utils.isEqual(pathModel.getName(), name)) {
- return pathModel;
- }
- }
- for (GroupModel groupModel : groupModels) {
- pModel = groupModel.getPathModelByName(name);
- if (pModel != null && Utils.isEqual(pModel.getName(), name)) return pModel;
- }
- return pModel;
- }
-
- public ClipPathModel getClipPathModelByName(String name) {
- ClipPathModel cModel = null;
- for (ClipPathModel clipPathModel : getClipPathModels()) {
- if (Utils.isEqual(clipPathModel.getName(), name)) {
- return clipPathModel;
- }
- }
- for (GroupModel groupModel : getGroupModels()) {
- cModel = groupModel.getClipPathModelByName(name);
- if (cModel != null && Utils.isEqual(cModel.getName(), name)) return cModel;
- }
- return cModel;
- }
-
- public Matrix getOriginalTransformMatrix() {
- return originalTransformMatrix;
- }
-
- public GroupModel getParent() {
- return parent;
- }
-
- public void setParent(GroupModel parent) {
- this.parent = parent;
- }
-
- public void addGroupModel(GroupModel groupModel) {
- groupModels.add(groupModel);
- }
-
- public ArrayList getGroupModels() {
- return groupModels;
- }
-
- public void addPathModel(PathModel pathModel) {
- pathModels.add(pathModel);
- }
-
- public ArrayList getPathModels() {
- return pathModels;
- }
-
- public void addClipPathModel(ClipPathModel clipPathModel) {
- clipPathModels.add(clipPathModel);
- }
-
- public ArrayList getClipPathModels() {
- return clipPathModels;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public float getRotation() {
- return rotation;
- }
-
- public void setRotation(float rotation) {
- this.rotation = rotation;
- updateAndScalePaths();
- }
-
- public float getPivotX() {
- return pivotX;
- }
-
- public void setPivotX(float pivotX) {
- this.pivotX = pivotX;
- }
-
- public float getPivotY() {
- return pivotY;
- }
-
- public void setPivotY(float pivotY) {
- this.pivotY = pivotY;
- }
-
- public float getScaleX() {
- return scaleX;
- }
-
- public void setScaleX(float scaleX) {
- this.scaleX = scaleX;
- updateAndScalePaths();
- }
-
- public float getScaleY() {
- return scaleY;
- }
-
- public void setScaleY(float scaleY) {
- this.scaleY = scaleY;
- updateAndScalePaths();
- }
-
- public float getTranslateX() {
- return translateX;
- }
-
- public void setTranslateX(float translateX) {
- this.translateX = translateX;
- updateAndScalePaths();
- }
-
- public float getTranslateY() {
- return translateY;
- }
-
- public void setTranslateY(float translateY) {
- this.translateY = translateY;
- updateAndScalePaths();
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java
deleted file mode 100644
index d4ac4f252..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/PathModel.java
+++ /dev/null
@@ -1,317 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.models;
-
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PathMeasure;
-import android.graphics.RectF;
-
-import com.sdsmdg.harjot.vectormaster.DefaultValues;
-import com.sdsmdg.harjot.vectormaster.utilities.Utils;
-import com.sdsmdg.harjot.vectormaster.utilities.parser.PathParser;
-
-public class PathModel {
-
- private String name;
-
- private float fillAlpha;
- private int fillColor;
-
- private Path.FillType fillType;
-
- private String pathData;
-
- private float trimPathStart, trimPathEnd, trimPathOffset;
-
- private float strokeAlpha;
- private int strokeColor;
- private Paint.Cap strokeLineCap;
- private Paint.Join strokeLineJoin;
- private float strokeMiterLimit;
- private float strokeWidth;
-
- private float strokeRatio;
-
- private boolean isFillAndStroke = false;
-
- // Support for trim-paths is not available
-
- private Path originalPath;
- private Path path;
- private Path trimmedPath;
- private Paint pathPaint;
-
- private Matrix scaleMatrix;
-
- public PathModel() {
- fillAlpha = DefaultValues.PATH_FILL_ALPHA;
- fillColor = DefaultValues.PATH_FILL_COLOR;
- fillType = DefaultValues.PATH_FILL_TYPE;
- trimPathStart = DefaultValues.PATH_TRIM_PATH_START;
- trimPathEnd = DefaultValues.PATH_TRIM_PATH_END;
- trimPathOffset = DefaultValues.PATH_TRIM_PATH_OFFSET;
- strokeAlpha = DefaultValues.PATH_STROKE_ALPHA;
- strokeColor = DefaultValues.PATH_STROKE_COLOR;
- strokeLineCap = DefaultValues.PATH_STROKE_LINE_CAP;
- strokeLineJoin = DefaultValues.PATH_STROKE_LINE_JOIN;
- strokeMiterLimit = DefaultValues.PATH_STROKE_MITER_LIMIT;
- strokeWidth = DefaultValues.PATH_STROKE_WIDTH;
- strokeRatio = DefaultValues.PATH_STROKE_RATIO;
-
- pathPaint = new Paint();
- pathPaint.setAntiAlias(true);
- updatePaint();
- }
-
- public void updatePaint() {
- pathPaint.setStrokeWidth(strokeWidth * strokeRatio);
-
- if (fillColor != Color.TRANSPARENT && strokeColor != Color.TRANSPARENT) {
- isFillAndStroke = true;
- } else if (fillColor != Color.TRANSPARENT) {
- pathPaint.setColor(fillColor);
- pathPaint.setAlpha(Utils.getAlphaFromFloat(fillAlpha));
- pathPaint.setStyle(Paint.Style.FILL);
- isFillAndStroke = false;
- } else if (strokeColor != Color.TRANSPARENT) {
- pathPaint.setColor(strokeColor);
- pathPaint.setAlpha(Utils.getAlphaFromFloat(strokeAlpha));
- pathPaint.setStyle(Paint.Style.STROKE);
- isFillAndStroke = false;
- } else {
- pathPaint.setColor(Color.TRANSPARENT);
- }
-
- pathPaint.setStrokeCap(strokeLineCap);
- pathPaint.setStrokeJoin(strokeLineJoin);
- pathPaint.setStrokeMiter(strokeMiterLimit);
- }
-
- public void buildPath(boolean useLegacyParser) {
- if (useLegacyParser) {
- originalPath =
- com.sdsmdg.harjot.vectormaster.utilities.legacyparser.PathParser.createPathFromPathData(
- pathData);
- } else {
- originalPath = PathParser.doPath(pathData);
- }
- if (originalPath != null) originalPath.setFillType(fillType);
-
- path = new Path(originalPath);
- }
-
- public void makeStrokePaint() {
- pathPaint.setColor(strokeColor);
- pathPaint.setAlpha(Utils.getAlphaFromFloat(strokeAlpha));
- pathPaint.setStyle(Paint.Style.STROKE);
- }
-
- public void makeFillPaint() {
- pathPaint.setColor(fillColor);
- pathPaint.setAlpha(Utils.getAlphaFromFloat(fillAlpha));
- pathPaint.setStyle(Paint.Style.FILL);
- }
-
- public void transform(Matrix matrix) {
- scaleMatrix = matrix;
-
- trimPath();
- }
-
- public void trimPath() {
- if (scaleMatrix != null) {
- if (trimPathStart == 0 && trimPathEnd == 1 && trimPathOffset == 0) {
- path = new Path(originalPath);
- path.transform(scaleMatrix);
- } else {
- PathMeasure pathMeasure = new PathMeasure(originalPath, false);
- float length = pathMeasure.getLength();
- trimmedPath = new Path();
- pathMeasure.getSegment(
- (trimPathStart + trimPathOffset) * length,
- (trimPathEnd + trimPathOffset) * length,
- trimmedPath,
- true);
- path = new Path(trimmedPath);
- path.transform(scaleMatrix);
- }
- }
- }
-
- public Path getTrimmedPath() {
- return trimmedPath;
- }
-
- public void setTrimmedPath(Path trimmedPath) {
- this.trimmedPath = trimmedPath;
- }
-
- public Path getPath() {
- return path;
- }
-
- public void setPath(Path path) {
- this.path = path;
- }
-
- public Path getScaledAndOffsetPath(float offsetX, float offsetY, float scaleX, float scaleY) {
- Path newPath = new Path(path);
- newPath.offset(offsetX, offsetY);
- newPath.transform(getScaleMatrix(newPath, scaleX, scaleY));
- return newPath;
- }
-
- public Matrix getScaleMatrix(Path srcPath, float scaleX, float scaleY) {
- Matrix scaleMatrix = new Matrix();
- RectF rectF = new RectF();
- srcPath.computeBounds(rectF, true);
- scaleMatrix.setScale(scaleX, scaleY, rectF.left, rectF.top);
- return scaleMatrix;
- }
-
- public Paint getPathPaint() {
- return pathPaint;
- }
-
- public void setPathPaint(Paint pathPaint) {
- this.pathPaint = pathPaint;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public float getFillAlpha() {
- return fillAlpha;
- }
-
- public void setFillAlpha(float fillAlpha) {
- this.fillAlpha = fillAlpha;
- updatePaint();
- }
-
- public int getFillColor() {
- return fillColor;
- }
-
- public void setFillColor(int fillColor) {
- this.fillColor = fillColor;
- updatePaint();
- }
-
- public Path.FillType getFillType() {
- return fillType;
- }
-
- public void setFillType(Path.FillType fillType) {
- this.fillType = fillType;
- if (originalPath != null) originalPath.setFillType(fillType);
- }
-
- public String getPathData() {
- return pathData;
- }
-
- public void setPathData(String pathData) {
- this.pathData = pathData;
- }
-
- public float getTrimPathStart() {
- return trimPathStart;
- }
-
- public void setTrimPathStart(float trimPathStart) {
- this.trimPathStart = trimPathStart;
- trimPath();
- }
-
- public float getTrimPathEnd() {
- return trimPathEnd;
- }
-
- public void setTrimPathEnd(float trimPathEnd) {
- this.trimPathEnd = trimPathEnd;
- trimPath();
- }
-
- public float getTrimPathOffset() {
- return trimPathOffset;
- }
-
- public void setTrimPathOffset(float trimPathOffset) {
- this.trimPathOffset = trimPathOffset;
- trimPath();
- }
-
- public float getStrokeAlpha() {
- return strokeAlpha;
- }
-
- public void setStrokeAlpha(float strokeAlpha) {
- this.strokeAlpha = strokeAlpha;
- updatePaint();
- }
-
- public int getStrokeColor() {
- return strokeColor;
- }
-
- public void setStrokeColor(int strokeColor) {
- this.strokeColor = strokeColor;
- updatePaint();
- }
-
- public Paint.Cap getStrokeLineCap() {
- return strokeLineCap;
- }
-
- public void setStrokeLineCap(Paint.Cap strokeLineCap) {
- this.strokeLineCap = strokeLineCap;
- updatePaint();
- }
-
- public Paint.Join getStrokeLineJoin() {
- return strokeLineJoin;
- }
-
- public void setStrokeLineJoin(Paint.Join strokeLineJoin) {
- this.strokeLineJoin = strokeLineJoin;
- updatePaint();
- }
-
- public float getStrokeMiterLimit() {
- return strokeMiterLimit;
- }
-
- public void setStrokeMiterLimit(float strokeMiterLimit) {
- this.strokeMiterLimit = strokeMiterLimit;
- updatePaint();
- }
-
- public float getStrokeWidth() {
- return strokeWidth;
- }
-
- public void setStrokeWidth(float strokeWidth) {
- this.strokeWidth = strokeWidth;
- updatePaint();
- }
-
- public float getStrokeRatio() {
- return strokeRatio;
- }
-
- public void setStrokeRatio(float strokeRatio) {
- this.strokeRatio = strokeRatio;
- updatePaint();
- }
-
- public boolean isFillAndStroke() {
- return isFillAndStroke;
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java
deleted file mode 100644
index d7055403d..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/models/VectorModel.java
+++ /dev/null
@@ -1,217 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.models;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Path;
-
-import com.sdsmdg.harjot.vectormaster.enums.TintMode;
-
-import java.util.ArrayList;
-
-public class VectorModel {
-
- private String name;
-
- private float width, height;
-
- private float alpha = 1.0f;
-
- private boolean autoMirrored = false;
-
- private int tint = Color.TRANSPARENT;
- private TintMode tintMode = TintMode.SCR_IN;
-
- private float viewportWidth, viewportHeight;
-
- private ArrayList groupModels;
- private ArrayList pathModels;
- private ArrayList clipPathModels;
-
- private Path fullpath;
-
- private Matrix scaleMatrix;
-
- public VectorModel() {
- groupModels = new ArrayList<>();
- pathModels = new ArrayList<>();
- clipPathModels = new ArrayList<>();
- fullpath = new Path();
- }
-
- public void drawPaths(Canvas canvas, float offsetX, float offsetY, float scaleX, float scaleY) {
- for (ClipPathModel clipPathModel : clipPathModels) {
- canvas.clipPath(clipPathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY));
- }
- for (GroupModel groupModel : groupModels) {
- groupModel.drawPaths(canvas, offsetX, offsetY, scaleX, scaleY);
- }
- for (PathModel pathModel : pathModels) {
- if (pathModel.isFillAndStroke()) {
- pathModel.makeFillPaint();
- canvas.drawPath(
- pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY),
- pathModel.getPathPaint());
- pathModel.makeStrokePaint();
- canvas.drawPath(
- pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY),
- pathModel.getPathPaint());
- } else {
- canvas.drawPath(
- pathModel.getScaledAndOffsetPath(offsetX, offsetY, scaleX, scaleY),
- pathModel.getPathPaint());
- }
- }
- }
-
- public void drawPaths(Canvas canvas) {
- for (ClipPathModel clipPathModel : clipPathModels) {
- canvas.clipPath(clipPathModel.getPath());
- }
- for (GroupModel groupModel : groupModels) {
- groupModel.drawPaths(canvas);
- }
- for (PathModel pathModel : pathModels) {
- if (pathModel.isFillAndStroke()) {
- pathModel.makeFillPaint();
- canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint());
- pathModel.makeStrokePaint();
- canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint());
- } else {
- canvas.drawPath(pathModel.getPath(), pathModel.getPathPaint());
- }
- }
- }
-
- public void scaleAllPaths(Matrix scaleMatrix) {
- this.scaleMatrix = scaleMatrix;
- for (GroupModel groupModel : groupModels) {
- groupModel.scaleAllPaths(scaleMatrix);
- }
- for (PathModel pathModel : pathModels) {
- pathModel.transform(scaleMatrix);
- }
- for (ClipPathModel clipPathModel : clipPathModels) {
- clipPathModel.transform(scaleMatrix);
- }
- }
-
- public void scaleAllStrokeWidth(float ratio) {
- for (GroupModel groupModel : groupModels) {
- groupModel.scaleAllStrokeWidth(ratio);
- }
- for (PathModel pathModel : pathModels) {
- pathModel.setStrokeRatio(ratio);
- }
- }
-
- public void buildTransformMatrices() {
- for (GroupModel groupModel : groupModels) {
- groupModel.buildTransformMatrix();
- }
- }
-
- public void addGroupModel(GroupModel groupModel) {
- groupModels.add(groupModel);
- }
-
- public ArrayList getGroupModels() {
- return groupModels;
- }
-
- public void addPathModel(PathModel pathModel) {
- pathModels.add(pathModel);
- }
-
- public ArrayList getPathModels() {
- return pathModels;
- }
-
- public void addClipPathModel(ClipPathModel clipPathModel) {
- clipPathModels.add(clipPathModel);
- }
-
- public ArrayList getClipPathModels() {
- return clipPathModels;
- }
-
- public Path getFullpath() {
- return fullpath;
- }
-
- public void setFullpath(Path fullpath) {
- this.fullpath = fullpath;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public float getWidth() {
- return width;
- }
-
- public void setWidth(float width) {
- this.width = width;
- }
-
- public float getHeight() {
- return height;
- }
-
- public void setHeight(float height) {
- this.height = height;
- }
-
- public float getAlpha() {
- return alpha;
- }
-
- public void setAlpha(float alpha) {
- this.alpha = alpha;
- }
-
- public boolean isAutoMirrored() {
- return autoMirrored;
- }
-
- public void setAutoMirrored(boolean autoMirrored) {
- this.autoMirrored = autoMirrored;
- }
-
- public int getTint() {
- return tint;
- }
-
- public void setTint(int tint) {
- this.tint = tint;
- }
-
- public TintMode getTintMode() {
- return tintMode;
- }
-
- public void setTintMode(TintMode tintMode) {
- this.tintMode = tintMode;
- }
-
- public float getViewportWidth() {
- return viewportWidth;
- }
-
- public void setViewportWidth(float viewportWidth) {
- this.viewportWidth = viewportWidth;
- }
-
- public float getViewportHeight() {
- return viewportHeight;
- }
-
- public void setViewportHeight(float viewportHeight) {
- this.viewportHeight = viewportHeight;
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/Utils.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/Utils.java
deleted file mode 100644
index d8db0a418..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/Utils.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.utilities;
-
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-
-public class Utils {
-
- public static int getColorFromString(String value) {
- int color = Color.TRANSPARENT;
-
- if (value.length() == 4) {
- color =
- Color.parseColor(
- "#"
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(2)
- + value.charAt(2)
- + value.charAt(3)
- + value.charAt(3));
- } else if (value.length() == 7 || value.length() == 9) {
- color = Color.parseColor(value);
- } else if (value.length() == 2) {
- color =
- Color.parseColor(
- "#"
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(1)
- + value.charAt(1));
- }
-
- return color;
- }
-
- public static Path.FillType getFillTypeFromString(String value) {
- Path.FillType fillType = Path.FillType.WINDING;
- if (value.equals("1")) {
- fillType = Path.FillType.EVEN_ODD;
- }
- return fillType;
- }
-
- public static Paint.Cap getLineCapFromString(String value) {
- switch (value) {
- case "0":
- return Paint.Cap.BUTT;
- case "1":
- return Paint.Cap.ROUND;
- case "2":
- return Paint.Cap.SQUARE;
- default:
- return Paint.Cap.BUTT;
- }
- }
-
- public static Paint.Join getLineJoinFromString(String value) {
- switch (value) {
- case "0":
- return Paint.Join.MITER;
- case "1":
- return Paint.Join.ROUND;
- case "2":
- return Paint.Join.BEVEL;
- default:
- return Paint.Join.MITER;
- }
- }
-
- public static int getAlphaFromFloat(float value) {
- int newValue = (int) (255 * value);
- return Math.min(255, newValue);
- }
-
- public static float getAlphaFromInt(int value) {
- return (((float) value) / 255.0f);
- }
-
- public static int dpToPx(int dp) {
- return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
- }
-
- public static int pxToDp(int px) {
- return (int) (px / Resources.getSystem().getDisplayMetrics().density);
- }
-
- public static float getFloatFromDimensionString(String value) {
- if (value.contains("dip")) return Float.parseFloat(value.substring(0, value.length() - 3));
- else return Float.parseFloat(value.substring(0, value.length() - 2));
- }
-
- public static boolean isEqual(Object a, Object b) {
- return a == null && b == null || !(a == null || b == null) && a.equals(b);
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/legacyparser/PathParser.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/legacyparser/PathParser.java
deleted file mode 100644
index 0b66972d4..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/legacyparser/PathParser.java
+++ /dev/null
@@ -1,755 +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.sdsmdg.harjot.vectormaster.utilities.legacyparser;
-
-import android.graphics.Path;
-
-import androidx.annotation.Nullable;
-
-import com.itsaky.androidide.utils.ILogger;
-
-import java.util.ArrayList;
-
-/** This class is a duplicate of the PathParser.java in androidx.core.graphics package. */
-public class PathParser {
-
- private static final ILogger LOG = ILogger.newInstance("PathParser");
-
- // Copy from Arrays.copyOfRange() which is only available from API level 9.
- private PathParser() {}
-
- /**
- * @param pathData The string representing a path, the same as "d" string in svg file.
- * @return the generated Path object.
- */
- public static Path createPathFromPathData(String pathData) {
- Path path = new Path();
- PathDataNode[] nodes = createNodesFromPathData(pathData);
- if (nodes != null) {
- try {
- PathDataNode.nodesToPath(nodes, path);
- } catch (RuntimeException e) {
- throw new RuntimeException("Error in parsing " + pathData, e);
- }
- return path;
- }
- return null;
- }
- /**
- * @param pathData The string representing a path, the same as "d" string in svg file.
- * @return an array of the PathDataNode.
- */
- public static PathDataNode[] createNodesFromPathData(String pathData) {
- if (pathData == null) {
- return null;
- }
- int start = 0;
- int end = 1;
- ArrayList list = new ArrayList();
- while (end < pathData.length()) {
- end = nextStart(pathData, end);
- String s = pathData.substring(start, end).trim();
- if (s.length() > 0) {
- float[] val = getFloats(s);
- addNode(list, s.charAt(0), val);
- }
- start = end;
- end++;
- }
- if ((end - start) == 1 && start < pathData.length()) {
- addNode(list, pathData.charAt(start), new float[0]);
- }
- return list.toArray(new PathDataNode[list.size()]);
- }
-
- private static int nextStart(String s, int end) {
- char c;
- while (end < s.length()) {
- c = s.charAt(end);
- // Note that 'e' or 'E' are not valid path commands, but could be
- // used for floating point numbers' scientific notation.
- // Therefore, when searching for next command, we should ignore 'e'
- // and 'E'.
- if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) && c != 'e' && c != 'E') {
- return end;
- }
- end++;
- }
- return end;
- }
-
- private static void addNode(ArrayList list, char cmd, float[] val) {
- list.add(new PathDataNode(cmd, val));
- }
-
- /**
- * Parse the floats in the string. This is an optimized version of parseFloat(s.split(",|\\s"));
- *
- * @param s the string containing a command and list of floats
- * @return array of floats
- */
- private static float[] getFloats(String s) {
- if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') {
- return new float[0];
- }
- try {
- float[] results = new float[s.length()];
- int count = 0;
- int startPosition = 1;
- int endPosition = 0;
- ExtractFloatResult result = new ExtractFloatResult();
- int totalLength = s.length();
- // The startPosition should always be the first character of the
- // current number, and endPosition is the character after the current
- // number.
- while (startPosition < totalLength) {
- extract(s, startPosition, result);
- endPosition = result.mEndPosition;
- if (startPosition < endPosition) {
- results[count++] = Float.parseFloat(s.substring(startPosition, endPosition));
- }
- if (result.mEndWithNegOrDot) {
- // Keep the '-' or '.' sign with next number.
- startPosition = endPosition;
- } else {
- startPosition = endPosition + 1;
- }
- }
- return copyOfRange(results, 0, count);
- } catch (NumberFormatException e) {
- throw new RuntimeException("error in parsing \"" + s + "\"", e);
- }
- }
-
- /**
- * Copies elements from {@code original} into a new array, from indexes start (inclusive) to end
- * (exclusive). The original order of elements is preserved. If {@code end} is greater than {@code
- * original.length}, the result is padded with the value {@code 0.0f}.
- *
- * @param original the original array
- * @param start the start index, inclusive
- * @param end the end index, exclusive
- * @return the new array
- * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
- * @throws IllegalArgumentException if {@code start > end}
- * @throws NullPointerException if {@code original == null}
- */
- static float[] copyOfRange(float[] original, int start, int end) {
- if (start > end) {
- throw new IllegalArgumentException();
- }
- int originalLength = original.length;
- if (start < 0 || start > originalLength) {
- throw new ArrayIndexOutOfBoundsException();
- }
- int resultLength = end - start;
- int copyLength = Math.min(resultLength, originalLength - start);
- float[] result = new float[resultLength];
- System.arraycopy(original, start, result, 0, copyLength);
- return result;
- }
-
- /**
- * Calculate the position of the next comma or space or negative sign
- *
- * @param s the string to search
- * @param start the position to start searching
- * @param result the result of the extraction, including the position of the the starting position
- * of next number, whether it is ending with a '-'.
- */
- private static void extract(String s, int start, ExtractFloatResult result) {
- // Now looking for ' ', ',', '.' or '-' from the start.
- int currentIndex = start;
- boolean foundSeparator = false;
- result.mEndWithNegOrDot = false;
- boolean secondDot = false;
- boolean isExponential = false;
- for (; currentIndex < s.length(); currentIndex++) {
- boolean isPrevExponential = isExponential;
- isExponential = false;
- char currentChar = s.charAt(currentIndex);
- switch (currentChar) {
- case ' ':
- case ',':
- foundSeparator = true;
- break;
- case '-':
- // The negative sign following a 'e' or 'E' is not a separator.
- if (currentIndex != start && !isPrevExponential) {
- foundSeparator = true;
- result.mEndWithNegOrDot = true;
- }
- break;
- case '.':
- if (!secondDot) {
- secondDot = true;
- } else {
- // This is the second dot, and it is considered as a separator.
- foundSeparator = true;
- result.mEndWithNegOrDot = true;
- }
- break;
- case 'e':
- case 'E':
- isExponential = true;
- break;
- }
- if (foundSeparator) {
- break;
- }
- }
- // When there is nothing found, then we put the end position to the end
- // of the string.
- result.mEndPosition = currentIndex;
- }
-
- /**
- * @param source The array of PathDataNode to be duplicated.
- * @return a deep copy of the source.
- */
- public static PathDataNode[] deepCopyNodes(PathDataNode[] source) {
- if (source == null) {
- return null;
- }
- PathDataNode[] copy = new PathParser.PathDataNode[source.length];
- for (int i = 0; i < source.length; i++) {
- copy[i] = new PathDataNode(source[i]);
- }
- return copy;
- }
-
- /**
- * Update the target's data to match the source. Before calling this, make sure canMorph(target,
- * source) is true.
- *
- * @param target The target path represented in an array of PathDataNode
- * @param source The source path represented in an array of PathDataNode
- * @hide
- */
- public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
- for (int i = 0; i < source.length; i++) {
- target[i].mType = source[i].mType;
- for (int j = 0; j < source[i].mParams.length; j++) {
- target[i].mParams[j] = source[i].mParams[j];
- }
- }
- }
-
- /**
- * Interpolate between two arrays of PathDataNodes with the given fraction, and store the results
- * in the first parameter.
- *
- * @param target The resulting array of {@link PathDataNode} for the interpolation
- * @param from The array of {@link PathDataNode} when fraction is 0
- * @param to The array of {@link PathDataNode} when the fraction is 1
- * @param fraction A float fraction value in the range of 0 to 1
- * @return whether it's possible to interpolate between the two arrays of PathDataNodes
- * @see {@link #canMorph(PathDataNode[], PathDataNode[])}
- */
- public static boolean interpolatePathDataNodes(
- PathDataNode[] target, PathDataNode[] from, PathDataNode[] to, float fraction) {
- if (target == null || from == null || to == null) {
- throw new IllegalArgumentException(
- "The nodes to be interpolated and resulting nodes" + " cannot be null");
- }
- if (target.length != from.length || from.length != to.length) {
- throw new IllegalArgumentException(
- "The nodes to be interpolated and resulting nodes" + " must have the same length");
- }
- if (!canMorph(from, to)) {
- return false;
- }
- // Now do the interpolation
- for (int i = 0; i < target.length; i++) {
- target[i].interpolatePathDataNode(from[i], to[i], fraction);
- }
- return true;
- }
-
- /**
- * @param nodesFrom The source path represented in an array of PathDataNode
- * @param nodesTo The target path represented in an array of PathDataNode
- * @return whether the nodesFrom can morph into nodesTo
- */
- public static boolean canMorph(
- @Nullable PathDataNode[] nodesFrom, @Nullable PathDataNode[] nodesTo) {
- if (nodesFrom == null || nodesTo == null) {
- return false;
- }
- if (nodesFrom.length != nodesTo.length) {
- return false;
- }
- for (int i = 0; i < nodesFrom.length; i++) {
- if (nodesFrom[i].mType != nodesTo[i].mType
- || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
- * PathDataNode can represent the whole "d" attribute.
- */
- public static class PathDataNode {
- /** @hide */
- public char mType;
- /** @hide */
- public float[] mParams;
-
- PathDataNode(char type, float[] params) {
- this.mType = type;
- this.mParams = params;
- }
-
- PathDataNode(PathDataNode n) {
- mType = n.mType;
- mParams = copyOfRange(n.mParams, 0, n.mParams.length);
- }
- /**
- * Convert an array of PathDataNode to Path.
- *
- * @param node The source array of PathDataNode.
- * @param path The target Path object.
- */
- public static void nodesToPath(PathDataNode[] node, Path path) {
- float[] current = new float[6];
- char previousCommand = 'm';
- for (int i = 0; i < node.length; i++) {
- addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
- previousCommand = node[i].mType;
- }
- }
-
- private static void addCommand(
- Path path, float[] current, char previousCmd, char cmd, float[] val) {
- int incr = 2;
- float currentX = current[0];
- float currentY = current[1];
- float ctrlPointX = current[2];
- float ctrlPointY = current[3];
- float currentSegmentStartX = current[4];
- float currentSegmentStartY = current[5];
- float reflectiveCtrlPointX;
- float reflectiveCtrlPointY;
- switch (cmd) {
- case 'z':
- case 'Z':
- path.close();
- // Path is closed here, but we need to move the pen to the
- // closed position. So we cache the segment's starting position,
- // and restore it here.
- currentX = currentSegmentStartX;
- currentY = currentSegmentStartY;
- ctrlPointX = currentSegmentStartX;
- ctrlPointY = currentSegmentStartY;
- path.moveTo(currentX, currentY);
- break;
- case 'm':
- case 'M':
- case 'l':
- case 'L':
- case 't':
- case 'T':
- incr = 2;
- break;
- case 'h':
- case 'H':
- case 'v':
- case 'V':
- incr = 1;
- break;
- case 'c':
- case 'C':
- incr = 6;
- break;
- case 's':
- case 'S':
- case 'q':
- case 'Q':
- incr = 4;
- break;
- case 'a':
- case 'A':
- incr = 7;
- break;
- }
- for (int k = 0; k < val.length; k += incr) {
- switch (cmd) {
- case 'm': // moveto - Start a new sub-path (relative)
- currentX += val[k + 0];
- currentY += val[k + 1];
- if (k > 0) {
- // According to the spec, if a moveto is followed by multiple
- // pairs of coordinates, the subsequent pairs are treated as
- // implicit lineto commands.
- path.rLineTo(val[k + 0], val[k + 1]);
- } else {
- path.rMoveTo(val[k + 0], val[k + 1]);
- currentSegmentStartX = currentX;
- currentSegmentStartY = currentY;
- }
- break;
- case 'M': // moveto - Start a new sub-path
- currentX = val[k + 0];
- currentY = val[k + 1];
- if (k > 0) {
- // According to the spec, if a moveto is followed by multiple
- // pairs of coordinates, the subsequent pairs are treated as
- // implicit lineto commands.
- path.lineTo(val[k + 0], val[k + 1]);
- } else {
- path.moveTo(val[k + 0], val[k + 1]);
- currentSegmentStartX = currentX;
- currentSegmentStartY = currentY;
- }
- break;
- case 'l': // lineto - Draw a line from the current point (relative)
- path.rLineTo(val[k + 0], val[k + 1]);
- currentX += val[k + 0];
- currentY += val[k + 1];
- break;
- case 'L': // lineto - Draw a line from the current point
- path.lineTo(val[k + 0], val[k + 1]);
- currentX = val[k + 0];
- currentY = val[k + 1];
- break;
- case 'h': // horizontal lineto - Draws a horizontal line (relative)
- path.rLineTo(val[k + 0], 0);
- currentX += val[k + 0];
- break;
- case 'H': // horizontal lineto - Draws a horizontal line
- path.lineTo(val[k + 0], currentY);
- currentX = val[k + 0];
- break;
- case 'v': // vertical lineto - Draws a vertical line from the current point (r)
- path.rLineTo(0, val[k + 0]);
- currentY += val[k + 0];
- break;
- case 'V': // vertical lineto - Draws a vertical line from the current point
- path.lineTo(currentX, val[k + 0]);
- currentY = val[k + 0];
- break;
- case 'c': // curveto - Draws a cubic Bézier curve (relative)
- path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], val[k + 4], val[k + 5]);
- ctrlPointX = currentX + val[k + 2];
- ctrlPointY = currentY + val[k + 3];
- currentX += val[k + 4];
- currentY += val[k + 5];
- break;
- case 'C': // curveto - Draws a cubic Bézier curve
- path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], val[k + 4], val[k + 5]);
- currentX = val[k + 4];
- currentY = val[k + 5];
- ctrlPointX = val[k + 2];
- ctrlPointY = val[k + 3];
- break;
- case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
- reflectiveCtrlPointX = 0;
- reflectiveCtrlPointY = 0;
- if (previousCmd == 'c'
- || previousCmd == 's'
- || previousCmd == 'C'
- || previousCmd == 'S') {
- reflectiveCtrlPointX = currentX - ctrlPointX;
- reflectiveCtrlPointY = currentY - ctrlPointY;
- }
- path.rCubicTo(
- reflectiveCtrlPointX,
- reflectiveCtrlPointY,
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3]);
- ctrlPointX = currentX + val[k + 0];
- ctrlPointY = currentY + val[k + 1];
- currentX += val[k + 2];
- currentY += val[k + 3];
- break;
- case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
- reflectiveCtrlPointX = currentX;
- reflectiveCtrlPointY = currentY;
- if (previousCmd == 'c'
- || previousCmd == 's'
- || previousCmd == 'C'
- || previousCmd == 'S') {
- reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
- reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
- }
- path.cubicTo(
- reflectiveCtrlPointX,
- reflectiveCtrlPointY,
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3]);
- ctrlPointX = val[k + 0];
- ctrlPointY = val[k + 1];
- currentX = val[k + 2];
- currentY = val[k + 3];
- break;
- case 'q': // Draws a quadratic Bézier (relative)
- path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- ctrlPointX = currentX + val[k + 0];
- ctrlPointY = currentY + val[k + 1];
- currentX += val[k + 2];
- currentY += val[k + 3];
- break;
- case 'Q': // Draws a quadratic Bézier
- path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- ctrlPointX = val[k + 0];
- ctrlPointY = val[k + 1];
- currentX = val[k + 2];
- currentY = val[k + 3];
- break;
- case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
- reflectiveCtrlPointX = 0;
- reflectiveCtrlPointY = 0;
- if (previousCmd == 'q'
- || previousCmd == 't'
- || previousCmd == 'Q'
- || previousCmd == 'T') {
- reflectiveCtrlPointX = currentX - ctrlPointX;
- reflectiveCtrlPointY = currentY - ctrlPointY;
- }
- path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, val[k + 0], val[k + 1]);
- ctrlPointX = currentX + reflectiveCtrlPointX;
- ctrlPointY = currentY + reflectiveCtrlPointY;
- currentX += val[k + 0];
- currentY += val[k + 1];
- break;
- case 'T': // Draws a quadratic Bézier curve (reflective control point)
- reflectiveCtrlPointX = currentX;
- reflectiveCtrlPointY = currentY;
- if (previousCmd == 'q'
- || previousCmd == 't'
- || previousCmd == 'Q'
- || previousCmd == 'T') {
- reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
- reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
- }
- path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, val[k + 0], val[k + 1]);
- ctrlPointX = reflectiveCtrlPointX;
- ctrlPointY = reflectiveCtrlPointY;
- currentX = val[k + 0];
- currentY = val[k + 1];
- break;
- case 'a': // Draws an elliptical arc
- // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
- drawArc(
- path,
- currentX,
- currentY,
- val[k + 5] + currentX,
- val[k + 6] + currentY,
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3] != 0,
- val[k + 4] != 0);
- currentX += val[k + 5];
- currentY += val[k + 6];
- ctrlPointX = currentX;
- ctrlPointY = currentY;
- break;
- case 'A': // Draws an elliptical arc
- drawArc(
- path,
- currentX,
- currentY,
- val[k + 5],
- val[k + 6],
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3] != 0,
- val[k + 4] != 0);
- currentX = val[k + 5];
- currentY = val[k + 6];
- ctrlPointX = currentX;
- ctrlPointY = currentY;
- break;
- }
- previousCmd = cmd;
- }
- current[0] = currentX;
- current[1] = currentY;
- current[2] = ctrlPointX;
- current[3] = ctrlPointY;
- current[4] = currentSegmentStartX;
- current[5] = currentSegmentStartY;
- }
-
- private static void drawArc(
- Path p,
- float x0,
- float y0,
- float x1,
- float y1,
- float a,
- float b,
- float theta,
- boolean isMoreThanHalf,
- boolean isPositiveArc) {
- /* Convert rotation angle from degrees to radians */
- double thetaD = Math.toRadians(theta);
- /* Pre-compute rotation matrix entries */
- double cosTheta = Math.cos(thetaD);
- double sinTheta = Math.sin(thetaD);
- /* Transform (x0, y0) and (x1, y1) into unit space */
- /* using (inverse) rotation, followed by (inverse) scale */
- double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
- double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
- double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
- double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
- /* Compute differences and averages */
- double dx = x0p - x1p;
- double dy = y0p - y1p;
- double xm = (x0p + x1p) / 2;
- double ym = (y0p + y1p) / 2;
- /* Solve for intersecting unit circles */
- double dsq = dx * dx + dy * dy;
- if (dsq == 0.0) {
- LOG.warn("Points are coincident");
- return; /* Points are coincident */
- }
- double disc = 1.0 / dsq - 1.0 / 4.0;
- if (disc < 0.0) {
- LOG.warn("Points are too far apart " + dsq);
- float adjust = (float) (Math.sqrt(dsq) / 1.99999);
- drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta, isMoreThanHalf, isPositiveArc);
- return; /* Points are too far apart */
- }
- double s = Math.sqrt(disc);
- double sdx = s * dx;
- double sdy = s * dy;
- double cx;
- double cy;
- if (isMoreThanHalf == isPositiveArc) {
- cx = xm - sdy;
- cy = ym + sdx;
- } else {
- cx = xm + sdy;
- cy = ym - sdx;
- }
- double eta0 = Math.atan2((y0p - cy), (x0p - cx));
- double eta1 = Math.atan2((y1p - cy), (x1p - cx));
- double sweep = (eta1 - eta0);
- if (isPositiveArc != (sweep >= 0)) {
- if (sweep > 0) {
- sweep -= 2 * Math.PI;
- } else {
- sweep += 2 * Math.PI;
- }
- }
- cx *= a;
- cy *= b;
- double tcx = cx;
- cx = cx * cosTheta - cy * sinTheta;
- cy = tcx * sinTheta + cy * cosTheta;
- arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
- }
-
- /**
- * Converts an arc to cubic Bezier segments and records them in p.
- *
- * @param p The target for the cubic Bezier segments
- * @param cx The x coordinate center of the ellipse
- * @param cy The y coordinate center of the ellipse
- * @param a The radius of the ellipse in the horizontal direction
- * @param b The radius of the ellipse in the vertical direction
- * @param e1x E(eta1) x coordinate of the starting point of the arc
- * @param e1y E(eta2) y coordinate of the starting point of the arc
- * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
- * @param start The start angle of the arc on the ellipse
- * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
- */
- private static void arcToBezier(
- Path p,
- double cx,
- double cy,
- double a,
- double b,
- double e1x,
- double e1y,
- double theta,
- double start,
- double sweep) {
- // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
- // and http://www.spaceroots.org/documents/ellipse/node22.html
- // Maximum of 45 degrees per cubic Bezier segment
- int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
- double eta1 = start;
- double cosTheta = Math.cos(theta);
- double sinTheta = Math.sin(theta);
- double cosEta1 = Math.cos(eta1);
- double sinEta1 = Math.sin(eta1);
- double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
- double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
- double anglePerSegment = sweep / numSegments;
- for (int i = 0; i < numSegments; i++) {
- double eta2 = eta1 + anglePerSegment;
- double sinEta2 = Math.sin(eta2);
- double cosEta2 = Math.cos(eta2);
- double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
- double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
- double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
- double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
- double tanDiff2 = Math.tan((eta2 - eta1) / 2);
- double alpha = Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
- double q1x = e1x + alpha * ep1x;
- double q1y = e1y + alpha * ep1y;
- double q2x = e2x - alpha * ep2x;
- double q2y = e2y - alpha * ep2y;
- // Adding this no-op call to workaround a proguard related issue.
- p.rLineTo(0, 0);
- p.cubicTo((float) q1x, (float) q1y, (float) q2x, (float) q2y, (float) e2x, (float) e2y);
- eta1 = eta2;
- e1x = e2x;
- e1y = e2y;
- ep1x = ep2x;
- ep1y = ep2y;
- }
- }
-
- /**
- * The current PathDataNode will be interpolated between the nodeFrom and
- * nodeTo according to the fraction.
- *
- * @param nodeFrom The start value as a PathDataNode.
- * @param nodeTo The end value as a PathDataNode
- * @param fraction The fraction to interpolate.
- */
- public void interpolatePathDataNode(
- PathDataNode nodeFrom, PathDataNode nodeTo, float fraction) {
- mType = nodeFrom.mType;
- for (int i = 0; i < nodeFrom.mParams.length; i++) {
- mParams[i] = nodeFrom.mParams[i] * (1 - fraction) + nodeTo.mParams[i] * fraction;
- }
- }
- }
-
- private static class ExtractFloatResult {
- // We need to return the position of the next separator and whether the
- // next float starts with a '-' or a '.'.
- int mEndPosition;
- boolean mEndWithNegOrDot;
-
- ExtractFloatResult() {}
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/parser/ParserHelper.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/parser/ParserHelper.java
deleted file mode 100644
index 46c791d58..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/parser/ParserHelper.java
+++ /dev/null
@@ -1,394 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.utilities.parser;
-
-/*
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
- Changes Copyright 2011 Google Inc.
-*/
-
-/**
- * Parses numbers from SVG text. Based on the Batik Number Parser (Apache 2 License).
- *
- * @author Apache Software Foundation, Larva Labs LLC
- */
-class ParserHelper {
-
- /** Array of powers of ten. Using double instead of float gives a tiny bit more precision. */
- private static final double[] pow10 = new double[128];
-
- static {
- for (int i = 0; i < pow10.length; i++) {
- pow10[i] = Math.pow(10, i);
- }
- }
-
- private final CharSequence s;
- private final int n;
- public int pos;
- private char current;
-
- public ParserHelper(CharSequence s) {
- this.s = s;
- this.pos = 0;
- n = s.length();
- current = s.charAt(pos);
- }
-
- // Computes a float from mantissa and exponent.
- private static float buildFloat(int mant, int exp) {
- if (exp < -125 || mant == 0) {
- return 0.0f;
- }
-
- if (exp >= 128) {
- return (mant > 0) ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY;
- }
-
- if (exp == 0) {
- return mant;
- }
-
- if (mant >= (1 << 26)) {
- mant++; // round up trailing bits if they will be dropped.
- }
-
- return (float) ((exp > 0) ? mant * pow10[exp] : mant / pow10[-exp]);
- }
-
- public void skipWhitespace() {
- while (pos < n) {
- if (Character.isWhitespace(s.charAt(pos))) {
- advance();
- } else {
- break;
- }
- }
- }
-
- public void advance() {
- current = read();
- }
-
- public float nextFloat() {
- skipWhitespace();
- float f = parseFloat();
- skipNumberSeparator();
- return f;
- }
-
- private char read() {
- if (pos < n) {
- pos++;
- }
- if (pos == n) {
- return '\0';
- } else {
- return s.charAt(pos);
- }
- }
-
- private void reportUnexpectedCharacterError(char c) {
- throw new RuntimeException("Unexpected char '" + c + "'.");
- }
-
- void skipNumberSeparator() {
- while (pos < n) {
- char c = s.charAt(pos);
- switch (c) {
- case ' ':
- case ',':
- case '\n':
- case '\t':
- advance();
- break;
- default:
- return;
- }
- }
- }
-
- // Parses the content of the buffer and converts it to a float.
- float parseFloat() {
- int mant = 0;
- int mantDig = 0;
- boolean mantPos = true;
- boolean mantRead = false;
-
- int exp = 0;
- int expDig = 0;
- int expAdj = 0;
- boolean expPos = true;
-
- switch (current) {
- case '-':
- mantPos = false;
- // fallthrough
- case '+':
- current = read();
- }
- m1:
- switch (current) {
- default:
- return Float.NaN;
-
- case '.':
- break;
-
- case '0':
- mantRead = true;
- l:
- for (; ; ) {
- current = read();
- switch (current) {
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break l;
- case '.':
- case 'e':
- case 'E':
- break m1;
- default:
- return 0.0f;
- case '0':
- }
- }
-
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- mantRead = true;
- l:
- for (; ; ) {
- if (mantDig < 9) {
- mantDig++;
- mant = mant * 10 + (current - '0');
- } else {
- expAdj++;
- }
- current = read();
- switch (current) {
- default:
- break l;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- }
- }
- }
-
- if (current == '.') {
- current = read();
- m2:
- switch (current) {
- default:
- case 'e':
- case 'E':
- if (!mantRead) {
- reportUnexpectedCharacterError(current);
- return 0.0f;
- }
- break;
-
- case '0':
- if (mantDig == 0) {
- l:
- for (; ; ) {
- current = read();
- expAdj--;
- switch (current) {
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break l;
- default:
- if (!mantRead) {
- return 0.0f;
- }
- break m2;
- case '0':
- }
- }
- }
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- l:
- for (; ; ) {
- if (mantDig < 9) {
- mantDig++;
- mant = mant * 10 + (current - '0');
- expAdj--;
- }
- current = read();
- switch (current) {
- default:
- break l;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- }
- }
- }
- }
-
- switch (current) {
- case 'e':
- case 'E':
- current = read();
- switch (current) {
- default:
- reportUnexpectedCharacterError(current);
- return 0f;
- case '-':
- expPos = false;
- case '+':
- current = read();
- switch (current) {
- default:
- reportUnexpectedCharacterError(current);
- return 0f;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- }
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- }
-
- en:
- switch (current) {
- case '0':
- l:
- for (; ; ) {
- current = read();
- switch (current) {
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- break l;
- default:
- break en;
- case '0':
- }
- }
-
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- l:
- for (; ; ) {
- if (expDig < 3) {
- expDig++;
- exp = exp * 10 + (current - '0');
- }
- current = read();
- switch (current) {
- default:
- break l;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- }
- }
- }
- default:
- }
-
- if (!expPos) {
- exp = -exp;
- }
- exp += expAdj;
- if (!mantPos) {
- mant = -mant;
- }
-
- return buildFloat(mant, exp);
- }
-}
diff --git a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/parser/PathParser.java b/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/parser/PathParser.java
deleted file mode 100644
index 7ba0d147e..000000000
--- a/xml-inflater/src/main/java/com/sdsmdg/harjot/vectormaster/utilities/parser/PathParser.java
+++ /dev/null
@@ -1,342 +0,0 @@
-package com.sdsmdg.harjot.vectormaster.utilities.parser;
-
-import android.graphics.Path;
-import android.graphics.RectF;
-import android.util.Log;
-
-public class PathParser {
-
- private static final String TAG = "PATH_PARSER";
-
- /*
- * This is where the hard-to-parse paths are handled.
- * Uppercase rules are absolute positions, lowercase are relative.
- * Types of path rules:
- *
- *
- * - M/m - (x y)+ - Move to (without drawing)
- *
- Z/z - (no params) - Close path (back to starting point)
- *
- L/l - (x y)+ - Line to
- *
- H/h - x+ - Horizontal ine to
- *
- V/v - y+ - Vertical line to
- *
- C/c - (x1 y1 x2 y2 x y)+ - Cubic bezier to
- *
- S/s - (x2 y2 x y)+ - Smooth cubic bezier to (shorthand that assumes the x2, y2 from previous C/S is the x1, y1 of this bezier)
- *
- Q/q - (x1 y1 x y)+ - Quadratic bezier to
- *
- T/t - (x y)+ - Smooth quadratic bezier to (assumes previous control point is "reflection" of last one w.r.t. to current point)
- *
- *
- * Numbers are separate by whitespace, comma or nothing at all (!) if they are self-delimiting, (ie. begin with a - sign)
- */
- public static Path doPath(String s) {
- int n = s.length();
- ParserHelper ph = new ParserHelper(s);
- ph.skipWhitespace();
- Path p = new Path();
- float lastX = 0;
- float lastY = 0;
- float lastX1 = 0;
- float lastY1 = 0;
- float contourInitialX = 0;
- float contourInitialY = 0;
- RectF r = new RectF();
- char prevCmd = 'm';
- char cmd = 'x';
- while (ph.pos < n) {
- char next = s.charAt(ph.pos);
- if (!Character.isDigit(next) && !(next == '.') && !(next == '-')) {
- cmd = next;
- ph.advance();
- } else if (cmd == 'M') { // implied command
- cmd = 'L';
- } else if (cmd == 'm') { // implied command
- cmd = 'l';
- } else { // implied command
- // ignore
- }
- p.computeBounds(r, true);
- // Log.d(TAG, " " + cmd + " " + r);
- // Util.debug("* Commands remaining: '" + path + "'.");
- boolean wasCurve = false;
- switch (cmd) {
- case 'M':
- case 'm':
- {
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 'm') {
- p.rMoveTo(x, y);
- lastX += x;
- lastY += y;
- } else {
- p.moveTo(x, y);
- lastX = x;
- lastY = y;
- }
- contourInitialX = lastX;
- contourInitialY = lastY;
- break;
- }
- case 'Z':
- case 'z':
- {
- /// p.lineTo(contourInitialX, contourInitialY);
- p.close();
- lastX = contourInitialX;
- lastY = contourInitialY;
- break;
- }
- case 'L':
- case 'l':
- {
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 'l') {
- if ((prevCmd == 'M' || prevCmd == 'm') && x == 0 && y == 0) {
- p.addCircle(x, y, 1f, Path.Direction.CW);
- } else {
- p.rLineTo(x, y);
- lastX += x;
- lastY += y;
- }
- } else {
- if ((prevCmd == 'M' || prevCmd == 'm') && x == lastX && y == lastY) {
- p.addCircle(x, y, 1f, Path.Direction.CW);
- } else {
- p.lineTo(x, y);
- lastX = x;
- lastY = y;
- }
- }
- break;
- }
- case 'H':
- case 'h':
- {
- float x = ph.nextFloat();
- if (cmd == 'h') {
- p.rLineTo(x, 0);
- lastX += x;
- } else {
- p.lineTo(x, lastY);
- lastX = x;
- }
- break;
- }
- case 'V':
- case 'v':
- {
- float y = ph.nextFloat();
- if (cmd == 'v') {
- p.rLineTo(0, y);
- lastY += y;
- } else {
- p.lineTo(lastX, y);
- lastY = y;
- }
- break;
- }
- case 'C':
- case 'c':
- {
- wasCurve = true;
- float x1 = ph.nextFloat();
- float y1 = ph.nextFloat();
- float x2 = ph.nextFloat();
- float y2 = ph.nextFloat();
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 'c') {
- x1 += lastX;
- x2 += lastX;
- x += lastX;
- y1 += lastY;
- y2 += lastY;
- y += lastY;
- }
- p.cubicTo(x1, y1, x2, y2, x, y);
- lastX1 = x2;
- lastY1 = y2;
- lastX = x;
- lastY = y;
- break;
- }
- case 'S':
- case 's':
- {
- wasCurve = true;
- float x2 = ph.nextFloat();
- float y2 = ph.nextFloat();
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 's') {
- x2 += lastX;
- x += lastX;
- y2 += lastY;
- y += lastY;
- }
- float x1 = 2 * lastX - lastX1;
- float y1 = 2 * lastY - lastY1;
- p.cubicTo(x1, y1, x2, y2, x, y);
- lastX1 = x2;
- lastY1 = y2;
- lastX = x;
- lastY = y;
- break;
- }
- case 'A':
- case 'a':
- {
- float rx = ph.nextFloat();
- float ry = ph.nextFloat();
- float theta = ph.nextFloat();
- int largeArc = (int) ph.nextFloat();
- int sweepArc = (int) ph.nextFloat();
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 'a') {
- x += lastX;
- y += lastY;
- }
- drawArc(p, lastX, lastY, x, y, rx, ry, theta, largeArc == 1, sweepArc == 1);
- lastX = x;
- lastY = y;
- break;
- }
- case 'T':
- case 't':
- {
- wasCurve = true;
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 't') {
- x += lastX;
- y += lastY;
- }
- float x1 = 2 * lastX - lastX1;
- float y1 = 2 * lastY - lastY1;
- p.cubicTo(lastX, lastY, x1, y1, x, y);
- lastX = x;
- lastY = y;
- lastX1 = x1;
- lastY1 = y1;
- break;
- }
- case 'Q':
- case 'q':
- {
- wasCurve = true;
- float x1 = ph.nextFloat();
- float y1 = ph.nextFloat();
- float x = ph.nextFloat();
- float y = ph.nextFloat();
- if (cmd == 'q') {
- x += lastX;
- y += lastY;
- x1 += lastX;
- y1 += lastY;
- }
- p.cubicTo(lastX, lastY, x1, y1, x, y);
- lastX1 = x1;
- lastY1 = y1;
- lastX = x;
- lastY = y;
- break;
- }
- default:
- Log.w(TAG, "Invalid path command: " + cmd);
- ph.advance();
- }
- prevCmd = cmd;
- if (!wasCurve) {
- lastX1 = lastX;
- lastY1 = lastY;
- }
- ph.skipWhitespace();
- }
- return p;
- }
-
- /*
- * Elliptical arc implementation based on the SVG specification notes
- * Adapted from the Batik library (Apache-2 license) by SAU
- */
- private static void drawArc(
- Path path,
- double x0,
- double y0,
- double x,
- double y,
- double rx,
- double ry,
- double angle,
- boolean largeArcFlag,
- boolean sweepFlag) {
- double dx2 = (x0 - x) / 2.0;
- double dy2 = (y0 - y) / 2.0;
- angle = Math.toRadians(angle % 360.0);
- double cosAngle = Math.cos(angle);
- double sinAngle = Math.sin(angle);
-
- double x1 = (cosAngle * dx2 + sinAngle * dy2);
- double y1 = (-sinAngle * dx2 + cosAngle * dy2);
- rx = Math.abs(rx);
- ry = Math.abs(ry);
-
- double Prx = rx * rx;
- double Pry = ry * ry;
- double Px1 = x1 * x1;
- double Py1 = y1 * y1;
-
- // check that radii are large enough
- double radiiCheck = Px1 / Prx + Py1 / Pry;
- if (radiiCheck > 1) {
- rx = Math.sqrt(radiiCheck) * rx;
- ry = Math.sqrt(radiiCheck) * ry;
- Prx = rx * rx;
- Pry = ry * ry;
- }
-
- // Step 2 : Compute (cx1, cy1)
- double sign = (largeArcFlag == sweepFlag) ? -1 : 1;
- double sq = ((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) / ((Prx * Py1) + (Pry * Px1));
- sq = (sq < 0) ? 0 : sq;
- double coef = (sign * Math.sqrt(sq));
- double cx1 = coef * ((rx * y1) / ry);
- double cy1 = coef * -((ry * x1) / rx);
-
- double sx2 = (x0 + x) / 2.0;
- double sy2 = (y0 + y) / 2.0;
- double cx = sx2 + (cosAngle * cx1 - sinAngle * cy1);
- double cy = sy2 + (sinAngle * cx1 + cosAngle * cy1);
-
- // Step 4 : Compute the angleStart (angle1) and the angleExtent (dangle)
- double ux = (x1 - cx1) / rx;
- double uy = (y1 - cy1) / ry;
- double vx = (-x1 - cx1) / rx;
- double vy = (-y1 - cy1) / ry;
- double p, n;
-
- // Compute the angle start
- n = Math.sqrt((ux * ux) + (uy * uy));
- p = ux; // (1 * ux) + (0 * uy)
- sign = (uy < 0) ? -1.0 : 1.0;
- double angleStart = Math.toDegrees(sign * Math.acos(p / n));
-
- // Compute the angle extent
- n = Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
- p = ux * vx + uy * vy;
- sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0;
- double angleExtent = Math.toDegrees(sign * Math.acos(p / n));
- if (!sweepFlag && angleExtent > 0) {
- angleExtent -= 360f;
- } else if (sweepFlag && angleExtent < 0) {
- angleExtent += 360f;
- }
- angleExtent %= 360f;
- angleStart %= 360f;
-
- RectF oval =
- new RectF((float) (cx - rx), (float) (cy - ry), (float) (cx + rx), (float) (cy + ry));
- path.addArc(oval, (float) angleStart, (float) angleExtent);
- }
-}