diff --git a/.idea/misc.xml b/.idea/misc.xml
index 7119b2011..88818fd3e 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -24,6 +24,7 @@
+
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 2f7a92258..fd3b8aa5b 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
@@ -17,6 +17,7 @@
package com.itsaky.androidide.fragments.sheets;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -24,6 +25,7 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
import androidx.transition.ChangeBounds;
import androidx.transition.TransitionManager;
@@ -36,6 +38,7 @@ import com.itsaky.androidide.databinding.LayoutAttrEditorSheetBinding;
import com.itsaky.androidide.databinding.LayoutAttrEditorSheetItemBinding;
import com.itsaky.androidide.models.IconTextListItem;
import com.itsaky.androidide.models.XMLAttribute;
+import com.itsaky.androidide.utils.AttributeDialogs;
import com.itsaky.androidide.utils.DialogUtils;
import com.itsaky.androidide.utils.Logger;
import com.itsaky.layoutinflater.IView;
@@ -44,8 +47,11 @@ import com.itsaky.toaster.Toaster;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.stream.Collectors;
+import static com.itsaky.attrinfo.models.Attr.*;
+
public class AttrEditorSheet extends BottomSheetDialogFragment implements SimpleIconTextAdapter.OnBindListener {
private static final List VIEW_ACTIONS = new ArrayList<> ();
@@ -76,6 +82,14 @@ public class AttrEditorSheet extends BottomSheetDialogFragment implements Simple
}
setupViewData ();
+
+ AttributeDialogs.init (getActivity ());
+ }
+
+ @Override
+ public void onDismiss (@NonNull DialogInterface dialog) {
+ AttributeDialogs.release ();
+ super.onDismiss (dialog);
}
public AttrEditorSheet setDeletionFailedListener (OnViewDeletionFailedListener listener) {
@@ -111,6 +125,31 @@ public class AttrEditorSheet extends BottomSheetDialogFragment implements Simple
LOG.error (getString (R.string.msg_no_attr_format), attribute);
return;
}
+
+ showEditorDialog (attribute);
+ }
+
+ private void showEditorDialog (@NonNull XMLAttribute attribute) {
+ final var format = attribute.getFormat ();
+ final var attr = attribute.getAttr ();
+
+ AlertDialog dialog = null;
+ if (hasFormat (format, DIMENSION)) {
+ if (attr == null) {
+ throw new IllegalStateException ("The provided attribute has not been resoleved.");
+ }
+
+ final var possibleValues = attr.possibleValues;
+ dialog = AttributeDialogs.dimensionEditor (possibleValues.toArray(new String[0]), attribute.getValue (), (dialog1, which) -> {
+ LOG.debug ("Dimension value changed to : " + attribute.getValue ());
+ });
+ }
+
+ // TODO Once the user has selected another value, update it for the view too.
+ }
+
+ private boolean hasFormat (int format, int check) {
+ return (format &check ) != 0;
}
@Override
diff --git a/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java b/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
index 697914c07..0b2a68e1f 100644
--- a/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
+++ b/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
@@ -21,8 +21,10 @@ import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.itsaky.androidide.app.StudioApp;
+import com.itsaky.attrinfo.models.Attr;
import com.itsaky.layoutinflater.IAttribute;
import com.itsaky.layoutinflater.impl.UiAttribute;
@@ -47,6 +49,8 @@ public class XMLAttribute extends UiAttribute implements Parcelable {
*/
private int format = -1;
+ private Attr attr;
+
public XMLAttribute (IAttribute attribute) {
this (attribute, true);
}
@@ -79,14 +83,18 @@ public class XMLAttribute extends UiAttribute implements Parcelable {
}
final var attrs = StudioApp.getInstance ().attrInfo ();
- final var attr = attrs.getAttribute (getAttributeName ());
- if (attr != null) {
- this.format = attr.format;
+ this.attr = attrs.getAttribute (getAttributeName ());
+ if (this.attr != null) {
+ this.format = this.attr.format;
}
return getFormat ();
}
+ public Attr getAttr () {
+ return attr;
+ }
+
public static final Creator CREATOR = new Creator () {
@NonNull
@Contract("_ -> new")
diff --git a/app/src/main/java/com/itsaky/androidide/utils/AttributeDialogs.java b/app/src/main/java/com/itsaky/androidide/utils/AttributeDialogs.java
new file mode 100644
index 000000000..17efddf16
--- /dev/null
+++ b/app/src/main/java/com/itsaky/androidide/utils/AttributeDialogs.java
@@ -0,0 +1,133 @@
+/*
+ * 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.utils;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+
+import static com.itsaky.androidide.utils.DialogUtils.newMaterialDialogBuilder;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+
+import com.itsaky.androidide.R;
+import com.itsaky.androidide.databinding.LayoutDimensionEditorBinding;
+
+/**
+ * Helper class for creating dialogs for editing view attributes.
+ *
+ * TODO Should we merge this into {@link DialogUtils}
+ * @author Akash Yadav
+ */
+public class AttributeDialogs {
+
+ private static final String DIMENSION_MATCH = "match_parent";
+ private static final String DIMENSION_WRAP = "wrap_content";
+
+ /**
+ * Context that will be used for creating dialogs.
+ * This must be initialized by calling {@link #init(Context)}
+ * and the reference must be released by calling {@link #release()}
+ */
+ private static Context mContext;
+
+ /**
+ * Initialize this class with the provided context.
+ * @param ctx The context that will be used for creating dialogs.
+ * @see #release()
+ */
+ public static void init (Context ctx) {
+ mContext = ctx;
+ }
+
+ /**
+ * Release the context instance stored in this class.
+ *
+ * @see #init(Context)
+ */
+ public static void release () {
+ mContext = null;
+ }
+
+ public static AlertDialog dimensionEditor (CharSequence[] values, CharSequence value, DialogInterface.OnClickListener onSubmit) {
+ final var binding = LayoutDimensionEditorBinding.inflate(LayoutInflater.from (mContext));
+ binding.choices.setOnCheckedChangeListener ((group, checkedId) -> {
+ binding.otherValue.setVisibility (binding.other.isChecked () ? View.VISIBLE : View.GONE);
+ });
+
+ if (DIMENSION_MATCH.equals (value)) {
+ binding.choices.check (R.id.match);
+ } else if (DIMENSION_WRAP.equals (value)) {
+ binding.choices.check (R.id.wrap);
+ } else {
+ binding.choices.check (R.id.other);
+ }
+
+ final var builder = newMaterialDialogBuilder (mContext);
+ builder.setView (binding.getRoot ());
+ builder.setPositiveButton (android.R.string.ok, ((dialog, which) -> {
+ dialog.dismiss ();
+ if (onSubmit != null) {
+ onSubmit.onClick (dialog, which);
+ }
+ }));
+ builder.setNegativeButton (android.R.string.cancel, (dialog, which) -> dialog.dismiss ());
+ return builder.show ();
+ }
+
+ /**
+ * @see #enumSelector(CharSequence[], int, DialogInterface.OnClickListener)
+ */
+ public static AlertDialog enumSelector (CharSequence[] values, CharSequence value, DialogInterface.OnClickListener onSelected) {
+ return enumSelector (values, findIndexOf (values, value), onSelected);
+ }
+
+ private static int findIndexOf (@NonNull CharSequence[] values, CharSequence value) {
+ for (int i=0;i {
+ dialog.dismiss ();
+ if (onSelected != null) {
+ onSelected.onClick (dialog, which);
+ }
+ });
+ return builder.show ();
+ }
+
+
+}
diff --git a/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java b/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java
index 384e69852..a54c2ec85 100644
--- a/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java
@@ -45,6 +45,16 @@ public class DialogUtils {
return new MaterialAlertDialogBuilder (context, R.style.AppTheme_MaterialAlertDialog);
}
+ /**
+ * Create a new alert dialog with two buttons: Yes and No.
+ * This method simply calls {@link #newYesNoDialog(Context, String, String, DialogInterface.OnClickListener, DialogInterface.OnClickListener)}
+ * with default values for title and message.
+ *
+ * @param context The context for the dialog.
+ * @param positiveClickListener A listener that will be invoked on the Yes button click.
+ * @param negativeClickListener A listener that will be invoked on the No button click.
+ * @return The newly created dialog.
+ */
@NonNull
public static MaterialAlertDialogBuilder newYesNoDialog (Context context,
DialogInterface.OnClickListener positiveClickListener,
@@ -56,6 +66,16 @@ public class DialogUtils {
negativeClickListener);
}
+ /**
+ * Create a new alert dialog with two buttons: Yes and No.
+ *
+ * @param context The context for the dialog.
+ * @param title The title of the dialog.
+ * @param message The message of the dialog.
+ * @param positiveClickListener A listener that will be invoked on the Yes button click.
+ * @param negativeClickListener A listener that will be invoked on the No button click.
+ * @return The newly created dialog instance.
+ */
@NonNull
public static MaterialAlertDialogBuilder newYesNoDialog (Context context,
String title,
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 faa55d8dc..b726336ba 100644
--- a/app/src/main/res/layout/layout_attr_editor_sheet.xml
+++ b/app/src/main/res/layout/layout_attr_editor_sheet.xml
@@ -23,7 +23,7 @@
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 62de0ece2..493358788 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -316,7 +316,7 @@
New value
wrap_content
match_parent
- Fixed
+ Other value
Enter dimension value
Applicable attributes
Actions