diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4387e023b..bbb481e9c 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -61,6 +61,7 @@
+
diff --git a/app/src/main/assets/data/common/gradle-plugin.zip b/app/src/main/assets/data/common/gradle-plugin.zip
index 02a5a8976..43b244430 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/fragments/attr/AbstractReferenceEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/AbstractReferenceEditor.java
new file mode 100644
index 000000000..69f461657
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/AbstractReferenceEditor.java
@@ -0,0 +1,106 @@
+/*
+ * 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 static com.itsaky.androidide.utils.Logger.instance;
+
+import android.text.Editable;
+import android.text.TextUtils;
+import android.widget.AutoCompleteTextView;
+
+import androidx.annotation.NonNull;
+
+import com.blankj.utilcode.util.ThreadUtils;
+import com.google.android.material.textfield.MaterialAutoCompleteTextView;
+import com.itsaky.androidide.adapters.AttrValueCompletionAdapter;
+import com.itsaky.androidide.utils.Logger;
+import com.itsaky.androidide.utils.TextWatcherAdapter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author Akash Yadav
+ */
+public abstract class AbstractReferenceEditor extends BaseValueEditorFragment {
+
+ private static final Logger LOG = instance ("ReferenceEditor");
+ public TextWatcherAdapter resInputWatcher;
+
+ @Override
+ protected void notifyValueChanged (@NonNull String newValue) {
+ try {
+ super.notifyValueChanged (newValue);
+ } catch (Throwable e) {
+ LOG.error ("Unable to update resource value to '" + newValue + "'", e);
+ }
+ }
+
+ protected void setupReferenceInput (MaterialAutoCompleteTextView referenceInput) {
+ Objects.requireNonNull (referenceInput);
+
+ referenceInput.setText (attribute.getValue ());
+
+ if (resInputWatcher != null) {
+ referenceInput.removeTextChangedListener (resInputWatcher);
+ }
+
+ resInputWatcher =
+ new TextWatcherAdapter () {
+ @Override
+ public void afterTextChanged (@NonNull Editable s) {
+ final var text = s.toString ().trim ();
+ if (TextUtils.isEmpty (text)) {
+ return;
+ }
+
+ notifyValueChanged (text);
+ }
+ };
+
+ referenceInput.addTextChangedListener (resInputWatcher);
+
+ CompletableFuture.supplyAsync (this::computeReferenceItems)
+ .whenComplete (
+ (list, error) -> handleAutoCompleteResult (list, error, referenceInput));
+ }
+
+ protected void handleAutoCompleteResult (
+ List list, Throwable error, AutoCompleteTextView referenceInput) {
+ if (list == null || list.isEmpty ()) {
+ LOG.error ("No completion items found");
+ LOG.error ("Error was:", error);
+ return;
+ }
+
+ LOG.debug ("Found", list.size (), "resource items for completion");
+
+ ThreadUtils.runOnUiThread (
+ () -> {
+ final var adapter = new AttrValueCompletionAdapter (requireContext (), list);
+ referenceInput.setThreshold (1);
+ referenceInput.setAdapter (adapter);
+ adapter.notifyDataSetChanged ();
+ });
+ }
+
+ protected List computeReferenceItems () {
+ return new ArrayList<> ();
+ }
+}
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
index dd0247772..8bd02650e 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/BooleanEditor.java
@@ -35,51 +35,61 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
-/** @author Akash Yadav */
-public class BooleanEditor extends ReferenceEditor {
-
+/**
+ * @author Akash Yadav
+ */
+public class BooleanEditor extends AbstractReferenceEditor {
+
private LayoutBooleanAttrEditorBinding binding;
-
+
@Nullable
@Override
- public View onCreateView(
+ public View onCreateView (
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
- this.binding = LayoutBooleanAttrEditorBinding.inflate(inflater, container, false);
- return this.binding.getRoot();
+ this.binding = LayoutBooleanAttrEditorBinding.inflate (inflater, container, false);
+ return this.binding.getRoot ();
}
-
+
@Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- this.binding.choiceGroup.setOnCheckedChangeListener(
+ public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated (view, savedInstanceState);
+
+ this.binding.choiceGroup.setOnCheckedChangeListener (
(group, checkedId) -> {
- final var checked = (RadioButton) group.findViewById(checkedId);
- notifyValueChanged(checked.getText().toString().trim());
+ final var checked = (RadioButton) group.findViewById (checkedId);
+ notifyValueChanged (checked.getText ().toString ().trim ());
});
-
- setupReferenceInput(
- (MaterialAutoCompleteTextView) this.binding.booleanResInput.getEditText());
+
+ switch (attribute.getValue ()) {
+ case "true":
+ this.binding.boolTrue.setChecked (true);
+ break;
+ case "false":
+ this.binding.boolFalse.setChecked (true);
+ }
+
+ setupReferenceInput (
+ (MaterialAutoCompleteTextView) this.binding.booleanResInput.getEditText ());
}
-
+
@Override
- protected List computeReferenceItems() {
- final var list = new ArrayList();
- final var tables = ValuesTableFactory.getAllTables();
- for (var entry : tables.entrySet()) {
- final var dimens = entry.getValue().getTable("bool");
+ protected List computeReferenceItems () {
+ final var list = new ArrayList ();
+ final var tables = ValuesTableFactory.getAllTables ();
+ for (var entry : tables.entrySet ()) {
+ final var dimens = entry.getValue ().getTable ("bool");
if (dimens != null) {
- list.addAll(
- dimens.keySet().stream().map("@bool/"::concat).collect(Collectors.toSet()));
+ list.addAll (
+ dimens.keySet ().stream ().map ("@bool/"::concat).collect (Collectors.toSet ()));
}
}
-
- list.addAll(
- FrameworkValues.listBools().stream()
- .map("@android:bool/"::concat)
- .collect(Collectors.toList()));
+
+ list.addAll (
+ FrameworkValues.listBools ().stream ()
+ .map ("@android:bool/"::concat)
+ .collect (Collectors.toList ()));
return list;
}
}
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
index e6559cc49..c146f2d46 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
@@ -18,6 +18,7 @@
package com.itsaky.androidide.fragments.attr;
import android.app.Dialog;
+import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -27,6 +28,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
+import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.colorpicker.ColorPickerView;
import com.itsaky.androidide.databinding.LayoutColorAttrEditorBinding;
import com.itsaky.androidide.utils.DialogUtils;
@@ -40,7 +42,7 @@ import java.util.stream.Collectors;
/**
* @author Akash Yadav
*/
-public class ColorEditor extends ReferenceEditor {
+public class ColorEditor extends AbstractReferenceEditor {
private LayoutColorAttrEditorBinding binding;
private Dialog colorPickerDialog;
@@ -58,6 +60,13 @@ public class ColorEditor extends ReferenceEditor {
this.binding.pickColor.setOnClickListener (v -> getColorPickerDialog ().show ());
setupReferenceInput ((MaterialAutoCompleteTextView) this.binding.colorResInput.getEditText ());
+
+ try {
+ final var col = Color.parseColor (attribute.getValue ());
+ this.binding.colorPreview.setCardBackgroundColor (col);
+ } catch (Throwable th) {
+ // ignored
+ }
}
@Override
@@ -78,6 +87,10 @@ public class ColorEditor extends ReferenceEditor {
FrameworkValues.listColors ().stream ()
.map ("@android:color/"::concat)
.collect (Collectors.toList ()));
+
+ final var resTable = StudioApp.getInstance ().getResourceTable ();
+ list.addAll (resTable.listResourceNames ("color"));
+
return list;
}
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
index 08a279ae3..381393485 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/DimensionEditor.java
@@ -19,9 +19,11 @@ package com.itsaky.androidide.fragments.attr;
import android.os.Bundle;
import android.text.Editable;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -35,88 +37,105 @@ import com.itsaky.inflater.values.FrameworkValues;
import com.itsaky.inflater.values.ValuesTableFactory;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
-/** @author Akash Yadav */
-public class DimensionEditor extends ReferenceEditor {
-
- private static final Logger LOG = Logger.instance("DimensionEditor");
+/**
+ * @author Akash Yadav
+ */
+public class DimensionEditor extends AbstractReferenceEditor {
+
+ private static final Logger LOG = Logger.instance ("DimensionEditor");
public TextWatcherAdapter dimensionInputWatcher;
-
+
private LayoutDimensionAttrEditorBinding binding;
private String[] dimensionUnits;
-
+
@Nullable
@Override
- public View onCreateView(
+ public View onCreateView (
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
- this.binding = LayoutDimensionAttrEditorBinding.inflate(inflater, container, false);
- return this.binding.getRoot();
+ this.binding = LayoutDimensionAttrEditorBinding.inflate (inflater, container, false);
+ return this.binding.getRoot ();
}
-
+
@Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
+ public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated (view, savedInstanceState);
+
final var dimensionInput =
- Objects.requireNonNull(this.binding.dimensionInput.getEditText());
+ Objects.requireNonNull (this.binding.dimensionInput.getEditText ());
+ setDimensionValue (dimensionInput);
if (dimensionInputWatcher != null) {
- dimensionInput.removeTextChangedListener(dimensionInputWatcher);
+ dimensionInput.removeTextChangedListener (dimensionInputWatcher);
}
-
+
dimensionInputWatcher =
- new TextWatcherAdapter() {
+ new TextWatcherAdapter () {
@Override
- public void afterTextChanged(@NonNull Editable s) {
- final var text = s.toString().trim();
+ public void afterTextChanged (@NonNull Editable s) {
+ final var text = s.toString ().trim ();
final var unit =
- getDimensionUnits()[binding.unitSelector.getSelectedItemPosition()];
-
+ getDimensionUnits ()[binding.unitSelector.getSelectedItemPosition ()];
+
// This will call CommonParseUtils#parseDimension
- notifyValueChanged(text.concat(unit));
+ notifyValueChanged (text.concat (unit));
}
};
-
- dimensionInput.addTextChangedListener(dimensionInputWatcher);
-
+
+ dimensionInput.addTextChangedListener (dimensionInputWatcher);
+
final var dimensionResInput =
(MaterialAutoCompleteTextView)
- Objects.requireNonNull(binding.dimensionResInput.getEditText());
- setupReferenceInput(dimensionResInput);
+ Objects.requireNonNull (binding.dimensionResInput.getEditText ());
+ setupReferenceInput (dimensionResInput);
}
-
- @NonNull
- private String[] getDimensionUnits() {
- if (dimensionUnits == null) {
- dimensionUnits =
- requireContext().getResources().getStringArray(R.array.dimension_units);
- }
-
- return dimensionUnits;
- }
-
- @Override
- protected List computeReferenceItems() {
- final var list = new ArrayList();
- final var tables = ValuesTableFactory.getAllTables();
- for (var entry : tables.entrySet()) {
- final var dimens = entry.getValue().getTable("dimen");
- if (dimens != null) {
- list.addAll(
- dimens.keySet().stream()
- .map("@dimen/"::concat)
- .collect(Collectors.toSet()));
+
+ private void setDimensionValue (EditText dimensionInput) {
+ final var val = attribute.getValue ();
+ var dimension = val.substring (0, val.length () - 2);
+ if (TextUtils.isDigitsOnly (dimension)) {
+ dimensionInput.setText (dimension);
+ final var arr = requireContext ().getResources ().getStringArray (R.array.dimension_units);
+ final var index = Arrays.asList (arr).indexOf (val.substring (dimension.length ()));
+ if (index >= 0) {
+ this.binding.unitSelector.setSelection (index);
}
}
-
- list.addAll(
- FrameworkValues.listDimens().stream()
- .map("@android:dimen/"::concat)
- .collect(Collectors.toList()));
+ }
+
+ @NonNull
+ private String[] getDimensionUnits () {
+ if (dimensionUnits == null) {
+ dimensionUnits =
+ requireContext ().getResources ().getStringArray (R.array.dimension_units);
+ }
+
+ return dimensionUnits;
+ }
+
+ @Override
+ protected List computeReferenceItems () {
+ final var list = new ArrayList ();
+ final var tables = ValuesTableFactory.getAllTables ();
+ for (var entry : tables.entrySet ()) {
+ final var dimens = entry.getValue ().getTable ("dimen");
+ if (dimens != null) {
+ list.addAll (
+ dimens.keySet ().stream ()
+ .map ("@dimen/"::concat)
+ .collect (Collectors.toSet ()));
+ }
+ }
+
+ list.addAll (
+ FrameworkValues.listDimens ().stream ()
+ .map ("@android:dimen/"::concat)
+ .collect (Collectors.toList ()));
return list;
}
}
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
index 3c40809a5..d152527fe 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/EnumEditor.java
@@ -26,28 +26,39 @@ import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup;
import com.itsaky.androidide.utils.Logger;
-/** @author Akash Yadav */
+/**
+ * @author Akash Yadav
+ */
public class EnumEditor extends FixedValueEditor {
-
- private static final Logger LOG = Logger.instance("EnumEditor");
-
+
+ private static final Logger LOG = Logger.instance ("EnumEditor");
+
@Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- this.chipGroup.setSingleSelection(true);
- this.chipGroup.setSelectionRequired(true);
+ public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated (view, savedInstanceState);
+
+ this.chipGroup.setSingleSelection (true);
+ this.chipGroup.setSelectionRequired (true);
+
+ final var val = this.attribute.getValue ();
+ for (int i = 0; i < this.chipGroup.getChildCount (); i++) {
+ final var chip = (Chip) this.chipGroup.getChildAt (i);
+ if (val.equals (chip.getText ().toString ().trim ())) {
+ chip.setChecked (true);
+ break;
+ }
+ }
}
-
+
@Override
- protected void onCheckChanged(@NonNull ChipGroup group, int checkedId) {
- final var chip = (Chip) group.findViewById(group.getCheckedChipId());
+ protected void onCheckChanged (@NonNull ChipGroup group, int checkedId) {
+ final var chip = (Chip) group.findViewById (group.getCheckedChipId ());
if (chip == null) {
- LOG.error("Unable to update enum value. Checked Chip view is null.");
+ LOG.error ("Unable to update enum value. Checked Chip view is null.");
return;
}
-
- final var val = chip.getText().toString().trim();
- notifyValueChanged(val);
+
+ final var val = chip.getText ().toString ().trim ();
+ notifyValueChanged (val);
}
}
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
index c046ed258..fed9b02b3 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
@@ -32,6 +32,7 @@ import com.google.android.material.chip.ChipGroup;
import com.itsaky.androidide.utils.Logger;
import java.util.ArrayList;
+import java.util.Arrays;
/**
* @author Akash Yadav
@@ -47,6 +48,14 @@ public class FlagEditor extends FixedValueEditor {
this.chipGroup.setSingleSelection(false);
this.chipGroup.setSelectionRequired(true);
this.chipGroup.setOnCheckedChangeListener(null); // does not work for multiple selections
+
+ final var values = Arrays.asList (this.attribute.getValue ().split ("\\|"));
+ for (int i = 0; i < this.chipGroup.getChildCount (); i++) {
+ final var chip = (Chip) this.chipGroup.getChildAt (i);
+ if (values.contains (chip.getText ().toString ().trim ())) {
+ chip.setChecked (true);
+ }
+ }
}
@Override
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
index 671ca973b..b13da8e06 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/ReferenceEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/ReferenceEditor.java
@@ -14,91 +14,72 @@
* 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 static com.itsaky.androidide.utils.Logger.instance;
-
-import android.text.Editable;
-import android.text.TextUtils;
-import android.widget.AutoCompleteTextView;
+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 com.blankj.utilcode.util.ThreadUtils;
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
-import com.itsaky.androidide.adapters.AttrValueCompletionAdapter;
-import com.itsaky.androidide.utils.Logger;
-import com.itsaky.androidide.utils.TextWatcherAdapter;
+import com.itsaky.androidide.app.StudioApp;
+import com.itsaky.androidide.databinding.LayoutReferenceAttrEditorBinding;
+import com.itsaky.inflater.values.FrameworkValues;
+import com.itsaky.inflater.values.ValuesTableFactory;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
/**
* @author Akash Yadav
*/
-public class ReferenceEditor extends BaseValueEditorFragment {
+public class ReferenceEditor extends AbstractReferenceEditor {
- private static final Logger LOG = instance ("ReferenceEditor");
- public TextWatcherAdapter resInputWatcher;
+ private LayoutReferenceAttrEditorBinding binding;
+
+ @Nullable
+ @Override
+ public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ this.binding = LayoutReferenceAttrEditorBinding.inflate (inflater, container, false);
+ return this.binding.getRoot ();
+ }
@Override
- protected void notifyValueChanged (@NonNull String newValue) {
- try {
- super.notifyValueChanged (newValue);
- } catch (Throwable e) {
- LOG.error ("Unable to update resource value to '" + newValue + "'", e);
- }
- }
-
- protected void setupReferenceInput (MaterialAutoCompleteTextView referenceInput) {
- Objects.requireNonNull (referenceInput);
-
- if (resInputWatcher != null) {
- referenceInput.removeTextChangedListener (resInputWatcher);
- }
-
- resInputWatcher =
- new TextWatcherAdapter () {
- @Override
- public void afterTextChanged (@NonNull Editable s) {
- final var text = s.toString ().trim ();
- if (TextUtils.isEmpty (text)) {
- return;
- }
-
- notifyValueChanged (text);
- }
- };
-
- referenceInput.addTextChangedListener (resInputWatcher);
-
- CompletableFuture.supplyAsync (this::computeReferenceItems)
- .whenComplete (
- (list, error) -> handleAutoCompleteResult (list, error, referenceInput));
- }
-
- protected void handleAutoCompleteResult (
- List list, Throwable error, AutoCompleteTextView referenceInput) {
- if (list == null || list.isEmpty ()) {
- LOG.error ("No completion items found");
- LOG.error ("Error was:", error);
- return;
- }
-
- LOG.debug ("Found", list.size (), "resource items for completion");
-
- ThreadUtils.runOnUiThread (
- () -> {
- final var adapter = new AttrValueCompletionAdapter (requireContext (), list);
- referenceInput.setThreshold (1);
- referenceInput.setAdapter (adapter);
- adapter.notifyDataSetChanged ();
- });
+ public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated (view, savedInstanceState);
+
+ setupReferenceInput ((MaterialAutoCompleteTextView) this.binding.resInput.getEditText ());
}
+ @Override
protected List computeReferenceItems () {
- return new ArrayList<> ();
+ final var resTable = StudioApp.getInstance ().getResourceTable ();
+ final var list = new ArrayList<> (resTable.listResourceNames (null));
+
+ final var tables = ValuesTableFactory.getAllTables ();
+ for (var entry : tables.entrySet ()) {
+ final var resourceMap = entry.getValue ().getResourceMap ();
+ for (var resourceEntries : resourceMap.entrySet ()) {
+ final var name = resourceEntries.getKey ();
+ list.addAll (
+ resourceEntries
+ .getValue ()
+ .keySet ()
+ .stream ()
+ .map (("@android:" + name + "/")::concat)
+ .collect (Collectors.toList ()
+ )
+ );
+ }
+ }
+
+ list.addAll (FrameworkValues.listAllResources ());
+
+ return list;
}
}
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
index 2dd5ccec6..25e932144 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/StringEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/StringEditor.java
@@ -39,7 +39,7 @@ import java.util.stream.Collectors;
/**
* @author Akash Yadav
*/
-public class StringEditor extends ReferenceEditor {
+public class StringEditor extends AbstractReferenceEditor {
private LayoutStringAttrEditorBinding binding;
@@ -54,13 +54,15 @@ public class StringEditor extends ReferenceEditor {
public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated (view, savedInstanceState);
- Objects.requireNonNull (this.binding.stringInput.getEditText ()).addTextChangedListener (new TextWatcherAdapter () {
+ final var stringInput = Objects.requireNonNull (this.binding.stringInput.getEditText ());
+ stringInput.addTextChangedListener (new TextWatcherAdapter () {
@Override
public void afterTextChanged (@NonNull Editable s) {
notifyValueChanged (s.toString ());
}
});
+ stringInput.setText (this.attribute.getValue ());
setupReferenceInput ((MaterialAutoCompleteTextView) this.binding.stringResInput.getEditText ());
}
@@ -79,7 +81,7 @@ public class StringEditor extends ReferenceEditor {
}
list.addAll (
- FrameworkValues.listDimens ().stream ()
+ FrameworkValues.listStrings ().stream ()
.map ("@android:string/"::concat)
.collect (Collectors.toList ()));
return list;
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
index f46057ab0..3d4563bf6 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrValueEditorSheet.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrValueEditorSheet.java
@@ -49,6 +49,7 @@ 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.AbstractReferenceEditor;
import com.itsaky.androidide.fragments.attr.ReferenceEditor;
import com.itsaky.androidide.fragments.attr.StringEditor;
import com.itsaky.androidide.models.XMLAttribute;
diff --git a/app/src/main/java/com/itsaky/androidide/project/ProjectResourceTable.java b/app/src/main/java/com/itsaky/androidide/project/ProjectResourceTable.java
index 0f1a846a9..b65369e36 100644
--- a/app/src/main/java/com/itsaky/androidide/project/ProjectResourceTable.java
+++ b/app/src/main/java/com/itsaky/androidide/project/ProjectResourceTable.java
@@ -18,6 +18,7 @@
package com.itsaky.androidide.project;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.inflater.IResourceTable;
@@ -25,229 +26,287 @@ 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 Logger LOG = Logger.instance ("ProjectResourceFinder");
private File resDir;
private File color;
private File layout;
-
private File[] drawables;
private File[] mipmaps;
-
- private static final Logger LOG = Logger.instance("ProjectResourceFinder");
-
+
@Override
- public File findDrawable(@NonNull String name) {
+ public File findDrawable (@NonNull String name) {
for (File drawable : drawables) {
- final File file = findFileWithName(drawable.listFiles(), name);
+ 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);
+ 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);
-
+ public String findString (@NonNull String name) {
+ final var table = ValuesTableFactory.getTable (resDir);
+
if (table == null) {
return name;
}
-
- final var resource = table.findString(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)) {
+
+ 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 findBoolean(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
+ public String findBoolean (@NonNull String name) {
+ final var table = ValuesTableFactory.getTable (resDir);
+
if (table == null) {
return name;
}
-
- final var resource = table.findBoolean(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)) {
+
+ 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);
-
+ public String findInteger (@NonNull String name) {
+ final var table = ValuesTableFactory.getTable (resDir);
+
if (table == null) {
return name;
}
-
- final var resource = table.findInteger(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)) {
+
+ 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 String findColor(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
+ public String findColor (@NonNull String name) {
+ final var table = ValuesTableFactory.getTable (resDir);
+
if (table == null) {
return name;
}
-
- final var resource = table.findColor(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)) {
+
+ 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);
+ public String[] findArray (@NonNull String name) {
+ final var table = ValuesTableFactory.getTable (resDir);
if (table == null) {
- return new String[] {name};
+ return new String[]{name};
}
-
- final var resource = table.findArray(name);
+
+ final var resource = table.findArray (name);
if (resource == null) {
- return new String[] {name};
+ return new String[]{name};
}
-
- return resource.getValues();
+
+ return resource.getValues ();
}
-
+
@Override
- public String findDimension(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
+ public String findDimension (@NonNull String name) {
+ final var table = ValuesTableFactory.getTable (resDir);
+
if (table == null) {
return name;
}
-
- final var resource = table.findDimension(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)) {
+
+ final var value = resource.getValue ();
+ if (value.startsWith ("@dimen/")) {
+ var ref = value.substring ("@dimen/".length ());
+ if (name.equals (ref)) {
return name;
}
}
-
+
return value;
}
-
+
+ @NonNull
@Override
- public void setInflatingFile(@NonNull File file) {
- if (file.getParentFile() == null) {
- throw new IllegalArgumentException("Invalid inflating file");
+ 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;
}
-
- setupDirectories(
- file // layout file
- .getParentFile() // layout dir
- .getParentFile()); // res dir
}
-
- private void setupDirectories(File resDir) {
-
- if (resDir == null) {
- LOG.error("Null resource directory passed to resource finder. Ignoring.");
+
+ 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;
+ }
+
+ @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
+ }
+
+ 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.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"));
+
+ final File[] mipmaps = resDir.listFiles (new NameStartsWith ("mipmap"));
this.mipmaps = mipmaps == null ? new File[0] : mipmaps;
}
-
- private File findFileWithName(File[] files, String name) {
+
+ 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)) {
+ var simpleName = file.getName ();
+
+ if (simpleName.startsWith (name)) {
return file;
}
}
-
+
return null;
}
-
+
private static class NameStartsWith implements FileFilter {
-
+
private final String name;
-
- public NameStartsWith(String name) {
+
+ public NameStartsWith (String name) {
this.name = name;
}
-
+
@Override
- public boolean accept(@NonNull File file) {
- return file.getName().startsWith(name);
+ public boolean accept (@NonNull File file) {
+ return file.getName ().startsWith (name);
}
}
}
diff --git a/app/src/main/res/layout/layout_reference_attr_editor.xml b/app/src/main/res/layout/layout_reference_attr_editor.xml
new file mode 100644
index 000000000..4c2b70484
--- /dev/null
+++ b/app/src/main/res/layout/layout_reference_attr_editor.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 569bd465c..d39b2eef1 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -342,4 +342,5 @@
Color picker
String value
String resource
+ Any resource reference
diff --git a/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java b/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java
index 02d66f14d..7fa6b0d92 100644
--- a/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java
+++ b/xml-inflater/src/main/java/com/itsaky/inflater/IResourceTable.java
@@ -18,12 +18,16 @@
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 */
+/**
+ * Finds values in resources of a project
+ */
public interface IResourceTable {
-
+
/**
* Find the path of the drawable with the provided name
*
@@ -32,69 +36,79 @@ public interface IResourceTable {
* @param name The name of the drawable
* @return The drawable resource.
*/
- File findDrawable(@NonNull String name);
-
+ 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);
-
+ 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);
-
+ 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);
-
+ 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);
-
+ 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.
+ * 1dp, 12sp, 123px, etc.
*/
- String findDimension(@NonNull String name);
-
+ 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);
-
+ 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);
-
+ String findInteger (@NonNull String name);
+
/**
* Set the file which is currently being inflated.
*
* @param file The file.
*/
- void setInflatingFile(@NonNull File 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/values/FrameworkValues.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java
index 6284bf9f3..10e57b85f 100644
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java
+++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/FrameworkValues.java
@@ -25,6 +25,7 @@ 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.
@@ -32,42 +33,54 @@ import java.util.Objects;
* @author Akash Yadav
*/
public class FrameworkValues {
-
+
@NonNull
- public static List listDimens() {
- return listFields(android.R.dimen.class);
+ public static List listDimens () {
+ return listFields (android.R.dimen.class);
}
-
+
@NonNull
- public static List listBools() {
- return listFields(android.R.bool.class);
+ public static List listBools () {
+ return listFields (android.R.bool.class);
}
-
+
@NonNull
- public static List listStrings() {
- return listFields(android.R.string.class);
+ public static List listStrings () {
+ return listFields (android.R.string.class);
}
-
+
@NonNull
- public static List listColors() {
- return listFields(android.R.color.class);
+ public static List listColors () {
+ return listFields (android.R.color.class);
}
-
+
@NonNull
- private static List listFields(final Class> klass) {
- Objects.requireNonNull(klass);
-
- final var list = new ArrayList();
- final var fields = klass.getDeclaredFields();
+ 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)) {
+ final var mods = field.getModifiers ();
+ if (!isPublic (mods) || !isStatic (mods)) {
continue;
}
-
- list.add(field.getName());
+
+ list.add (field.getName ());
+ }
+
+ return list;
+ }
+
+ @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/ValuesTable.java b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java
index 7ca55d7d2..06f673b50 100644
--- a/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java
+++ b/xml-inflater/src/main/java/com/itsaky/inflater/values/ValuesTable.java
@@ -48,8 +48,8 @@ import java.util.Objects;
* @author Akash Yadav
*/
public class ValuesTable {
-
- private static final Logger LOG = Logger.instance("ValuesTable");
+
+ private static final Logger LOG = Logger.instance ("ValuesTable");
// TODO Parse styles and styleables
private final Map arrays;
private final Map strings;
@@ -57,185 +57,185 @@ public class ValuesTable {
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);
+
+ 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.
+ * this directory.
* @throws XmlPullParserException Thrown by {@link XmlPullParserFactory}.
- * @throws IOException Thrown by {@link XmlPullParser}.
+ * @throws IOException Thrown by {@link XmlPullParser}.
*/
@Nullable
- public static ValuesTable forDirectory(File valuesDirectory) throws Exception {
+ public static ValuesTable forDirectory (File valuesDirectory) throws Exception {
if (valuesDirectory == null) {
- LOG.error("Cannot create values table for directory: ", null);
+ LOG.error ("Cannot create values table for directory: ", null);
return null;
}
-
- if (!valuesDirectory.exists()) {
- LOG.error(
+
+ 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);
+
+ final var files = valuesDirectory.listFiles (ValuesTable::isValid);
if (files == null) {
- LOG.error("No files found in the given values directory");
+ LOG.error ("No files found in the given values directory");
return null;
}
-
- final var start = System.currentTimeMillis();
- final var values = new ValuesTable();
-
+
+ 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();
+ 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();
+ final var tag = parser.getName ();
+ if ("resources".equals (tag)) {
+ event = parser.next ();
continue;
}
-
- readTag(tag, parser, values);
+
+ readTag (tag, parser, values);
}
- event = parser.next();
+ event = parser.next ();
}
}
-
- final var duration = System.currentTimeMillis() - start;
- LOG.info(
- String.format(
- Locale.getDefault(),
+
+ 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)
+
+ private static void readTag (String tag, XmlPullParser parser, ValuesTable values)
throws Exception {
-
- if ("style".equals(tag) || "declare-styleable".equals(tag)) {
+
+ 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);
+ skip (parser);
return;
}
-
+
// TODO Should we check if these tags are specified within ?
- final var name = getName(parser);
+ final var name = getName (parser);
if (name == null) {
- LOG.error(String.format("A <%s> resource was found with no 'name' attribute", tag));
+ 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 ("item".equals (tag)) {
+ tag = parser.getAttributeValue (null, "type");
if (tag == null) {
- LOG.error("- resource value found but no 'type' was specified.");
+ 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);
+ 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();
+ final var value = parser.nextText ();
IResource resourceValue;
-
+
switch (tag) {
case "string":
- resourceValue = new StringResource(name, value);
- values.strings.put(name, resourceValue);
+ resourceValue = new StringResource (name, value);
+ values.strings.put (name, resourceValue);
break;
case "color":
- resourceValue = new ColorResource(name, value);
- values.colors.put(name, resourceValue);
+ resourceValue = new ColorResource (name, value);
+ values.colors.put (name, resourceValue);
break;
case "bool":
- resourceValue = new BooleanResource(name, value);
- values.booleans.put(name, resourceValue);
+ resourceValue = new BooleanResource (name, value);
+ values.booleans.put (name, resourceValue);
break;
case "dimen":
- resourceValue = new DimensionResource(name, value);
- values.dimens.put(name, resourceValue);
+ resourceValue = new DimensionResource (name, value);
+ values.dimens.put (name, resourceValue);
break;
case "integer":
- resourceValue = new IntegerResource(name, value);
- values.integers.put(name, resourceValue);
+ resourceValue = new IntegerResource (name, value);
+ values.integers.put (name, resourceValue);
break;
default:
- LOG.warn("Unknown or unsupported resource value tag:", tag);
+ LOG.warn ("Unknown or unsupported resource value tag:", tag);
break;
}
}
-
- private static void readArray(@NonNull XmlPullParser parser, ValuesTable values, String name)
+
+ 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) {
+ 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 child = parser.getName ();
+ if ("item".equals (child)) {
+ final var value = parser.nextText ();
+ items.add (value);
}
}
}
-
- final var arr = new String[items.size()];
+
+ final var arr = new String[items.size ()];
for (int i = 0; i < arr.length; i++) {
- arr[i] = items.get(i);
+ arr[i] = items.get (i);
}
-
- values.arrays.put(name, new ArrayResource(name, arr));
+
+ values.arrays.put (name, new ArrayResource (name, arr));
}
-
- private static void skip(@NonNull XmlPullParser parser)
+
+ private static void skip (@NonNull XmlPullParser parser)
throws XmlPullParserException, IOException {
- if (parser.getEventType() != XmlPullParser.START_TAG) {
- throw new IllegalStateException();
+ if (parser.getEventType () != XmlPullParser.START_TAG) {
+ throw new IllegalStateException ();
}
int depth = 1;
while (depth != 0) {
- switch (parser.next()) {
+ switch (parser.next ()) {
case XmlPullParser.END_TAG:
depth--;
break;
@@ -245,21 +245,26 @@ public class ValuesTable {
}
}
}
-
- private static String getName(@NonNull XmlPullParser parser) {
- return parser.getAttributeValue(null, "name");
+
+ 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);
+
+ 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);
+ 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.
*
@@ -267,133 +272,133 @@ public class ValuesTable {
* @return The resource value or {@code null} if there is no resource with the given name.
*/
@SuppressWarnings("unused")
- public IResource findResource(final String name) {
+ public IResource findResource (final String name) {
IResource value;
-
- value = findString(name);
+
+ value = findString (name);
if (value != null) {
return value;
}
-
- value = findColor(name);
+
+ value = findColor (name);
if (value != null) {
return value;
}
-
- value = findInteger(name);
+
+ value = findInteger (name);
if (value != null) {
return value;
}
-
- value = findDimension(name);
+
+ value = findDimension (name);
if (value != null) {
return value;
}
-
- value = findArray(name);
+
+ value = findArray (name);
if (value != null) {
return value;
}
-
- value = findBoolean(name);
+
+ value = findBoolean (name);
//noinspection RedundantIfStatement
if (value != null) {
return value;
}
-
+
return null;
}
-
- public ArrayResource findArray(final String name) {
- return (ArrayResource) arrays.getOrDefault(name, 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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();
+ 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();
+ final var tag = parser.getName ();
+ if ("resources".equals (tag)) {
+ event = parser.next ();
continue;
}
-
- ValuesTable.readTag(tag, parser, this);
+
+ ValuesTable.readTag (tag, parser, this);
}
- event = parser.next();
+ event = parser.next ();
}
-
- LOG.debug(
+
+ LOG.debug (
"Syncing with file",
- file.getName(),
+ file.getName (),
"took",
- (System.currentTimeMillis() - start),
+ (System.currentTimeMillis () - start),
"ms");
}
-
+
@NonNull
@Override
- public String toString() {
+ public String toString () {
return "ValuesTable{"
+ "strings="
+ strings