diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index 84d72f15f..2ec85e3e0 100755
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -41,5 +41,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index d198c0b07..56787aacd 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -49,6 +49,7 @@
+
diff --git a/app/build.gradle b/app/build.gradle
index 0ca08c786..3fc24fa3a 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,4 +1,5 @@
apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
@@ -112,6 +113,10 @@ dependencies {
implementation 'com.google.firebase:firebase-analytics'
implementation 'com.google.firebase:firebase-crashlytics'
implementation 'com.google.firebase:firebase-messaging'
+
+ // Kotlin
+ implementation "androidx.core:core-ktx:1.7.0"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// Local projects here
implementation project(':treeview')
diff --git a/app/src/main/assets/data/common/gradle-plugin.zip b/app/src/main/assets/data/common/gradle-plugin.zip
index 7d7f5e6c2..9fbc04022 100644
Binary files a/app/src/main/assets/data/common/gradle-plugin.zip and b/app/src/main/assets/data/common/gradle-plugin.zip differ
diff --git a/app/src/main/java/com/itsaky/androidide/adapters/AttrValueFormatTabAdapter.java b/app/src/main/java/com/itsaky/androidide/adapters/AttrValueFormatTabAdapter.java
new file mode 100644
index 000000000..75af0279b
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/adapters/AttrValueFormatTabAdapter.java
@@ -0,0 +1,128 @@
+/*
+ * 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.adapters;
+
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+
+import com.itsaky.androidide.fragments.attr.BaseValueEditorFragment;
+import com.itsaky.androidide.models.XMLAttribute;
+import com.itsaky.androidide.utils.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Adapter for value format tabs of attribute editor in UI Designer.
+ *
+ * @author Akash Yadav
+ */
+@SuppressWarnings("deprecation")
+public class AttrValueFormatTabAdapter extends FragmentStatePagerAdapter {
+
+ private static final Logger LOG = Logger.instance ("AttrValueEditorTabAdapter");
+ private final List mFragments = new ArrayList<> ();
+ private final List mTitles = new ArrayList<> ();
+ private final XMLAttribute attribute;
+
+ private final BaseValueEditorFragment.OnValueChangeListener changeListener;
+
+ public AttrValueFormatTabAdapter (@NonNull FragmentManager manager, XMLAttribute attribute, BaseValueEditorFragment.OnValueChangeListener changeListener) {
+ super (manager);
+ Objects.requireNonNull (attribute);
+
+ this.changeListener = changeListener;
+ this.attribute = attribute;
+ }
+
+ public void addFragment (final Class extends BaseValueEditorFragment> fragment, String title) {
+ Objects.requireNonNull (fragment);
+ Objects.requireNonNull (title);
+ if (TextUtils.isEmpty (title.trim ())) {
+ throw new IllegalArgumentException ("Invalid tab title");
+ }
+
+ mTitles.add (capitalize (title));
+ mFragments.add (createFragment (fragment, title));
+ }
+
+ @NonNull
+ private String capitalize (String title) {
+ title = title.trim ();
+
+ final var sb = new StringBuilder ();
+ for (int i = 0; i < title.length (); i++) {
+ var ch = title.charAt (i);
+ if (i == 0) {
+ ch = Character.toUpperCase (ch);
+ } else {
+ ch = Character.toLowerCase (ch);
+ }
+
+ sb.append (ch);
+ }
+
+ return sb.toString ();
+ }
+
+ public String getTitle (int position) {
+ return mTitles.get (position);
+ }
+
+ @NonNull
+ public Fragment createFragment (Class extends BaseValueEditorFragment> clazz, @NonNull final String name) {
+ try {
+ final var frag = clazz.newInstance ();
+ frag.setAttribute (attribute);
+ frag.setName (name);
+ frag.setOnValueChangeListener (this.changeListener);
+
+ return frag;
+ } catch (Throwable th) {
+ LOG.error ("Unable to create value editor fragment", th);
+ throw new RuntimeException (th);
+ }
+ }
+
+ public void removeAll () {
+ mFragments.clear ();
+ mTitles.clear ();
+ }
+
+ @NonNull
+ @Override
+ public Fragment getItem (int position) {
+ return mFragments.get (position);
+ }
+
+ @Override
+ public int getCount () {
+ return mFragments.size ();
+ }
+
+ @Nullable
+ @Override
+ public CharSequence getPageTitle (int position) {
+ return mTitles.get (position);
+ }
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/BaseValueEditorFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/BaseValueEditorFragment.java
new file mode 100644
index 000000000..fb13f0a8d
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/BaseValueEditorFragment.java
@@ -0,0 +1,71 @@
+/*
+ * 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.attr;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+
+import com.itsaky.androidide.models.XMLAttribute;
+import com.itsaky.inflater.IAttribute;
+
+import java.util.Objects;
+
+/**
+ * Base class for value editor fragment.
+ *
+ * @author Akash Yadav
+ */
+public class BaseValueEditorFragment extends Fragment {
+
+ protected OnValueChangeListener mValueChangeListener;
+ protected XMLAttribute attribute;
+ protected String name;
+
+ public void setAttribute (XMLAttribute attribute) {
+ this.attribute = attribute;
+ }
+
+ public void setName (String name) {
+ this.name = name;
+ }
+
+ public void setOnValueChangeListener (OnValueChangeListener listener) {
+ this.mValueChangeListener = listener;
+ }
+
+ protected void notifyValueChanged (@NonNull String newValue) {
+ Objects.requireNonNull (newValue);
+
+ if (mValueChangeListener != null) {
+ mValueChangeListener.onValueChanged (this.attribute, newValue);
+ }
+ }
+
+ /**
+ * Listener for listening for value change event.
+ */
+ public interface OnValueChangeListener {
+ /**
+ * Called when the value was changed.
+ *
+ * @param attribute The attribute whose value was changed.
+ * @param newValue The new value for the editor.
+ */
+ void onValueChanged (IAttribute attribute, String newValue);
+ }
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java
new file mode 100644
index 000000000..ae571f06b
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class BooleanEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
new file mode 100644
index 000000000..b2e59cbd6
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class ColorEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java
new file mode 100644
index 000000000..595ed1748
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class DimensionEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java
new file mode 100644
index 000000000..3faba0f93
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java
@@ -0,0 +1,60 @@
+/*
+ * 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.attr;
+
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.google.android.material.chip.Chip;
+
+import java.util.Objects;
+
+/**
+ * @author Akash Yadav
+ */
+public class EnumEditor extends FixedValueEditor {
+
+ @Override
+ public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated (view, savedInstanceState);
+
+ Objects.requireNonNull (this.attribute);
+ Objects.requireNonNull (this.chipGroup);
+
+ this.chipGroup.setSingleSelection (true);
+
+ final var attr = this.attribute.getAttr ();
+ for (var value : attr.possibleValues) {
+ if (TextUtils.isEmpty (value)) {
+ continue;
+ }
+
+ this.chipGroup.addView (newChip (value, value.equals (this.attribute.getValue ())));
+ }
+
+ this.chipGroup.setOnCheckedChangeListener ((group, checkedId) -> {
+ final var chip = (Chip) group.findViewById (checkedId);
+ final var val = chip.getText ().toString ().trim ();
+ notifyValueChanged (val);
+ });
+ }
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/FixedValueEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/FixedValueEditor.java
new file mode 100644
index 000000000..99d07d438
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/FixedValueEditor.java
@@ -0,0 +1,64 @@
+/*
+ * 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.attr;
+
+import android.content.res.ColorStateList;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+
+import com.google.android.material.chip.Chip;
+import com.google.android.material.chip.ChipGroup;
+import com.itsaky.androidide.R;
+
+/**
+ * @author Akash Yadav
+ */
+public abstract class FixedValueEditor extends BaseValueEditorFragment {
+
+ protected ChipGroup chipGroup;
+
+ @Nullable
+ @Override
+ public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ this.chipGroup = new ChipGroup (inflater.getContext ());
+ this.chipGroup.setLayoutParams (new ViewGroup.LayoutParams (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ this.chipGroup.setSelectionRequired (true);
+ this.chipGroup.setSingleSelection (false);
+
+ return this.chipGroup;
+ }
+
+ protected Chip newChip (String title, boolean checked) {
+ final var chip = new Chip (requireContext ());
+ chip.setText (title);
+ chip.setCheckedIcon (ContextCompat.getDrawable (requireContext (), R.drawable.ic_ok));
+ chip.setChecked (checked);
+ chip.setChipBackgroundColor (ContextCompat.getColorStateList (requireContext (), R.color.bg_enum_chips));
+ chip.setTextColor (ContextCompat.getColor (requireContext (), R.color.primaryTextColor));
+ chip.setLayoutParams (new ChipGroup.LayoutParams (ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ chip.setChipStrokeWidth (1f);
+ chip.setChipStrokeColor (ColorStateList.valueOf (ContextCompat.getColor (requireContext (), R.color.primaryDarkColor)));
+
+ return chip;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
new file mode 100644
index 000000000..ef46e6cc6
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class FlagEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/FloatEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/FloatEditor.java
new file mode 100644
index 000000000..944f2fe54
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/FloatEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class FloatEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/FractionEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/FractionEditor.java
new file mode 100644
index 000000000..fdc517950
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/FractionEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class FractionEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/IntegerEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/IntegerEditor.java
new file mode 100644
index 000000000..34f5452fd
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/IntegerEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class IntegerEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/ReferenceEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/ReferenceEditor.java
new file mode 100644
index 000000000..09040394a
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/ReferenceEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class ReferenceEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/StringEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/StringEditor.java
new file mode 100644
index 000000000..4207d67f9
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/StringEditor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.attr;
+
+/**
+ * @author Akash Yadav
+ */
+public class StringEditor extends BaseValueEditorFragment {
+}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java
index e6e03cbe3..ca36b3c82 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java
@@ -75,6 +75,7 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
private static final List VIEW_ACTIONS = new ArrayList<> ();
private static final Logger LOG = Logger.instance ("AttrBottomSheet");
private AttributeListSheet mAttrListSheet;
+ private AttrValueEditorSheet mValueEditorSheet;
private IView selectedView;
private File layout;
private LayoutAttrEditorSheetBinding binding;
@@ -108,8 +109,6 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
R.drawable.ic_view_select_parent));
}
- binding.valueEditorLayout.closeButton.setOnClickListener (v -> hideValueEditorLayout ());
-
setupViewData ();
AttributeDialogs.init (requireActivity ());
@@ -171,12 +170,11 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
return;
}
- showEditorDialog (attribute);
+ showValueEditorSheet (attribute);
}
- private void hideValueEditorLayout () {
- TransitionManager.beginDelayedTransition (binding.getRoot ());
- binding.valueEditorLayout.getRoot ().setVisibility (View.GONE);
+ private void showValueEditorSheet (@NonNull XMLAttribute attribute) {
+ getValueEditorSheet (attribute).show (getChildFragmentManager (), "attr_value_editor_sheet");
}
private void showEditorDialog (@NonNull XMLAttribute attribute) {
@@ -371,10 +369,36 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
return mAttrListSheet;
}
+ @NonNull
+ public AttrValueEditorSheet getValueEditorSheet (@NonNull XMLAttribute attribute) {
+
+ if (mValueEditorSheet == null) {
+ mValueEditorSheet = AttrValueEditorSheet.newInstance (attribute);
+ mValueEditorSheet.setOnValueChangeListener (this::onValueChanged);
+ }
+
+ mValueEditorSheet.setAttribute (attribute);
+ return mValueEditorSheet;
+ }
+
+ public void onValueChanged (@NonNull IAttribute attribute, String newValue) {
+ Objects.requireNonNull (this.selectedView);
+
+ 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);
+ }
+ }
+
private void addNewAttribute (@NonNull Attr attr) {
final XMLAttribute attribute = new XMLAttribute (attr.namespace, attr.name, "", false);
attribute.setAttr (attr);
- showEditorDialog (attribute);
+ showValueEditorSheet (attribute);
}
/**
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
new file mode 100644
index 000000000..e60da48a3
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrValueEditorSheet.java
@@ -0,0 +1,177 @@
+/*
+ * 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.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 org.jetbrains.annotations.Contract;
+
+import java.util.Objects;
+
+/**
+ * Sheet for editing value of an attribute.
+ *
+ * @author Akash Yadav
+ */
+public class AttrValueEditorSheet extends BottomSheetDialogFragment {
+
+ private static final String KEY_ATTRIBUTE = "attrEditorSheet_attribute";
+ private LayoutAttrValueEditorBinding binding;
+ private AttrValueFormatTabAdapter adapter;
+ private XMLAttribute attribute;
+
+ private BaseValueEditorFragment.OnValueChangeListener changeListener;
+
+ public void setOnValueChangeListener (BaseValueEditorFragment.OnValueChangeListener changeListener) {
+ this.changeListener = changeListener;
+ }
+
+ @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;
+ }
+
+ @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.getName (), 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, changeListener);
+
+ 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;
+ }
+}
diff --git a/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt b/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt
new file mode 100644
index 000000000..9984988fa
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt
@@ -0,0 +1,37 @@
+package com.itsaky.androidide.views;
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.ViewGroup
+import com.google.android.material.tabs.TabLayout
+
+// https://stackoverflow.com/a/65605542
+class ScalableTabLayout : TabLayout {
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
+ context,
+ attrs,
+ defStyleAttr
+ )
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val tabLayout = getChildAt(0) as ViewGroup
+ val childCount = tabLayout.childCount
+ if (childCount > 0) {
+ val widthPixels = MeasureSpec.getSize(widthMeasureSpec)
+ val tabMinWidth = widthPixels / childCount
+ var remainderPixels = widthPixels % childCount
+ for (i in 0 until childCount) {
+ val it = tabLayout.getChildAt(i)
+ if (remainderPixels > 0) {
+ it.minimumWidth = tabMinWidth + 1
+ remainderPixels--
+ } else {
+ it.minimumWidth = tabMinWidth
+ }
+ }
+ }
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/itsaky/androidide/views/ValueEditorTextView.java b/app/src/main/java/com/itsaky/androidide/views/ValueEditorTextView.java
deleted file mode 100644
index 613f01d45..000000000
--- a/app/src/main/java/com/itsaky/androidide/views/ValueEditorTextView.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.androidide.views;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.widget.ArrayAdapter;
-
-import androidx.annotation.NonNull;
-
-import com.google.android.material.textfield.MaterialAutoCompleteTextView;
-import com.itsaky.androidide.ui.edit.IValueSuggestionProvider;
-import com.itsaky.androidide.utils.TextWatcherAdapter;
-import com.itsaky.inflater.IAttribute;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * {@link MaterialAutoCompleteTextView} implementation used for providing suggestions while editing
- * attribute values.
- *
- * @author Akash Yadav
- */
-@SuppressLint("ViewConstructor")
-public class ValueEditorTextView extends MaterialAutoCompleteTextView {
-
- private final IAttribute attribute;
- private final int format;
- private final Set mSuggestionProviders = new HashSet<>();
-
- private final TextWatcher watcher =
- new TextWatcherAdapter() {
-
- @Override
- public void afterTextChanged(@NonNull Editable s) {
- final var prefix = s.toString();
- final var items = new ArrayList();
-
- for (IValueSuggestionProvider provider : mSuggestionProviders) {
- if (provider.checkFormat(format)) {
- items.addAll(provider.suggest(attribute, prefix));
- }
- }
-
- setThreshold(1);
- setAdapter(
- new ArrayAdapter<>(
- getContext(), android.R.layout.simple_list_item_1, items));
- }
- };
-
- public ValueEditorTextView(@NonNull Context context, IAttribute attribute, int format) {
- super(context);
- this.attribute = attribute;
- this.format = format;
-
- addTextChangedListener(this.watcher);
- }
-
- public void registerSuggestionProvider(IValueSuggestionProvider provider) {
- Objects.requireNonNull(provider);
- mSuggestionProviders.add(provider);
- }
-}
diff --git a/app/src/main/res/color/bg_enum_chips.xml b/app/src/main/res/color/bg_enum_chips.xml
new file mode 100644
index 000000000..cc51d1de2
--- /dev/null
+++ b/app/src/main/res/color/bg_enum_chips.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_attr_editor_sheet.xml b/app/src/main/res/layout/layout_attr_editor_sheet.xml
index bfe7c8816..52c5ab389 100644
--- a/app/src/main/res/layout/layout_attr_editor_sheet.xml
+++ b/app/src/main/res/layout/layout_attr_editor_sheet.xml
@@ -19,18 +19,16 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@color/content_background"
- android:paddingStart="16dp"
- android:paddingTop="16dp"
- android:paddingEnd="16dp"
- android:paddingBottom="8dp">
+ android:background="@color/content_background">
-
-
-
-
-
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@id/widget_name">
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_attr_value_editor.xml b/app/src/main/res/layout/layout_attr_value_editor.xml
index ee242ff37..c1ef861f5 100644
--- a/app/src/main/res/layout/layout_attr_value_editor.xml
+++ b/app/src/main/res/layout/layout_attr_value_editor.xml
@@ -19,19 +19,21 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/content_background"
- tools:padding="16dp">
+ android:background="@color/content_background">
@@ -40,35 +42,46 @@
android:id="@+id/attribute_format"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginEnd="16dp"
+ android:background="@color/primaryDarkColor"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:paddingBottom="8dp"
android:textColor="@color/secondaryTextColor_light"
android:textSize="14sp"
- app:layout_constraintEnd_toStartOf="@id/close_button"
+ app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/attribute_name"
tools:text="dimension|reference" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@id/attribute_format"
+ app:tabBackground="@android:color/transparent"
+ app:tabIndicatorAnimationMode="elastic"
+ app:tabIndicatorColor="@color/secondaryColor"
+ app:tabIndicatorHeight="3dp"
+ app:tabMaxWidth="0dp"
+ app:tabMode="scrollable"
+ app:tabSelectedTextColor="@color/secondaryColor"
+ app:tabTextAppearance="@style/AppTheme.TabLayout.Title" />
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 58c8f11aa..40eb0ad50 100755
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -5,6 +5,7 @@
#010101#ff5252#ff867f
+ #1FFF867F#c50e29#ffffff#bdbdbd
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
index 391a1e632..313ec164a 100755
--- a/sdk-info/src/main/java/com/itsaky/attrinfo/models/Attr.java
+++ b/sdk-info/src/main/java/com/itsaky/attrinfo/models/Attr.java
@@ -39,7 +39,7 @@ import java.util.regex.Pattern;
* @see com.itsaky.attrinfo.AttrInfo
*/
public class Attr {
-
+
public static final int REFERENCE = 1;
public static final int COLOR = 1 << 1;
public static final int BOOLEAN = 1 << 2;
@@ -51,122 +51,135 @@ public class Attr {
public static final int ENUM = 1 << 8;
public static final int FLAG = 1 << 9;
public static final int UNKNOWN = 1 << 10;
- private static final Logger LOG = Logger.instance("AttrInfo::Attr");
+
+ 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";
+
+ private static final Logger LOG = Logger.instance ("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) {
+ this (name, INamespace.ANDROID);
}
-
- public Attr(String name, INamespace namespace) {
+
+ public Attr (String name, INamespace namespace) {
this.name = name;
this.namespace = namespace;
- this.possibleValues = new TreeSet<>();
+ this.possibleValues = new TreeSet<> ();
}
-
- public static int formatForName(@NonNull String names) {
+
+ public static int formatForName (@NonNull String names) {
var result = 0;
- if (names.contains("|")) {
- for (var name : names.split(Pattern.quote("|"))) {
- result |= formatForSingleName(name);
+ if (names.contains ("|")) {
+ for (var name : names.split (Pattern.quote ("|"))) {
+ result |= formatForSingleName (name);
}
} else {
- result = formatForSingleName(names);
+ result = formatForSingleName (names);
}
return result;
}
-
+
@Contract(pure = true)
- public static int formatForSingleName(@NonNull String name) {
+ public static int formatForSingleName (@NonNull String name) {
switch (name) {
- case "reference":
+ case FORMAT_REFERENCE:
return REFERENCE;
- case "color":
+ case FORMAT_COLOR:
return COLOR;
- case "boolean":
+ case FORMAT_BOOLEAN:
return BOOLEAN;
- case "dimension":
+ case FORMAT_DIMENSION:
return DIMENSION;
- case "float":
+ case FORMAT_FLOAT:
return FLOAT;
- case "integer":
+ case FORMAT_INTEGER:
return INTEGER;
- case "fraction":
+ case FORMAT_FRACTION:
return FRACTION;
- case "string":
+ case FORMAT_STRING:
return STRING;
- case "enum":
+ case FORMAT_ENUM:
return ENUM;
- case "flag":
+ case FORMAT_FLAG:
return FLAG;
- default:
- return UNKNOWN;
}
+
+ return UNKNOWN;
}
-
- public static String createFormatText(int format) {
- final var formats = new ArrayList();
+
+ public static String createFormatText (int format) {
+ final var formats = new ArrayList ();
if ((format & REFERENCE) != 0) {
- formats.add("reference");
+ formats.add (FORMAT_REFERENCE);
}
-
+
if ((format & COLOR) != 0) {
- formats.add("color");
+ formats.add (FORMAT_COLOR);
}
-
+
if ((format & BOOLEAN) != 0) {
- formats.add("boolean");
+ formats.add (FORMAT_BOOLEAN);
}
-
+
if ((format & DIMENSION) != 0) {
- formats.add("dimension");
+ formats.add (FORMAT_DIMENSION);
}
-
+
if ((format & FLOAT) != 0) {
- formats.add("float");
+ formats.add (FORMAT_FLOAT);
}
-
+
if ((format & INTEGER) != 0) {
- formats.add("integer");
+ formats.add (FORMAT_INTEGER);
}
-
+
if ((format & FRACTION) != 0) {
- formats.add("fraction");
+ formats.add (FORMAT_FRACTION);
}
-
+
if ((format & STRING) != 0) {
- formats.add("string");
+ formats.add (FORMAT_STRING);
}
-
+
if ((format & ENUM) != 0) {
- formats.add("enum");
+ formats.add (FORMAT_ENUM);
}
-
+
if ((format & FLAG) != 0) {
- formats.add("flag");
+ formats.add (FORMAT_FLAG);
}
-
- if (formats.isEmpty()) {
- formats.add("unknown");
+
+ if (formats.isEmpty ()) {
+ formats.add ("unknown");
}
-
- return TextUtils.join("|", formats);
+
+ return TextUtils.join ("|", formats);
}
-
- public boolean hasPossibleValues() {
- return possibleValues != null && possibleValues.size() > 0;
+
+ public boolean hasPossibleValues () {
+ return possibleValues != null && possibleValues.size () > 0;
}
-
- public boolean hasFormat(int format) {
+
+ public boolean hasFormat (int format) {
return (this.format & format) != 0;
}
-
+
@NonNull
@Override
- public String toString() {
+ public String toString () {
return "Attr ["
+ " name: "
+ name
@@ -175,33 +188,33 @@ public class Attr {
+ namespace
+ "\n"
+ " values: "
- + TextUtils.join(", ", this.possibleValues)
+ + TextUtils.join (", ", this.possibleValues)
+ "\n"
+ " format: "
+ format
+ "\n"
+ "]";
}
-
+
@Override
- public boolean equals(Object o) {
+ public boolean equals (Object o) {
if (this == o) {
return true;
}
-
- if (o == null || getClass() != o.getClass()) {
+
+ 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);
+ && Objects.equals (namespace, attr.namespace)
+ && Objects.equals (name, attr.name)
+ && Objects.equals (possibleValues, attr.possibleValues);
}
-
+
@Override
- public int hashCode() {
- return Objects.hash(namespace, name, possibleValues, format);
+ public int hashCode () {
+ return Objects.hash (namespace, name, possibleValues, format);
}
}