mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Create base classes for attribute editors
This commit is contained in:
Generated
+2
@@ -31,7 +31,9 @@
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_attr_editor_sheet_item.xml" value="0.264" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_attr_value_editor.xml" value="0.264" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_attr_value_editor_dimension.xml" value="0.264" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_base_attr_editor.xml" value="0.20512820512820512" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_completion_item.xml" value="0.20512820512820512" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_dimension_editor.xml" value="0.264" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_simple_icon_text.xml" value="0.30128205128205127" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_widget_group_item.xml" value="0.33" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/android-ide/app/src/main/res/layout/layout_widget_item.xml" value="0.33" />
|
||||
|
||||
@@ -20,13 +20,16 @@ package com.itsaky.androidide.adapters;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.databinding.LayoutAttrEditorSheetItemBinding;
|
||||
import com.itsaky.androidide.models.XMLAttribute;
|
||||
|
||||
@@ -57,6 +60,10 @@ public class AttributeListAdapter extends RecyclerView.Adapter <AttributeListAda
|
||||
if (attr.isApplied ()) {
|
||||
sb.append (" = ");
|
||||
sb.append (attr.getValue (), new StyleSpan (Typeface.BOLD), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
final var length = attr.getValue ().length ();
|
||||
sb.setSpan (new ForegroundColorSpan (ContextCompat.getColor (binding.text.getContext (), R.color.primaryTextColor),
|
||||
));
|
||||
}
|
||||
|
||||
binding.text.setText (sb);
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.fragments.attreditors;
|
||||
|
||||
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.itsaky.androidide.databinding.LayoutDimensionEditorBinding;
|
||||
import com.itsaky.androidide.models.XMLAttribute;
|
||||
import com.itsaky.attrinfo.models.Attr;
|
||||
|
||||
public class DimensionAttrEditor extends IAttrEditorFragment {
|
||||
|
||||
private LayoutDimensionEditorBinding binding;
|
||||
|
||||
@Override
|
||||
protected IAttrEditorFragment newInstance (XMLAttribute attribute) {
|
||||
final var fragment = new DimensionAttrEditor ();
|
||||
Bundle args = new Bundle ();
|
||||
args.putParcelable (ATTRIBUTE_KEY, attribute);
|
||||
fragment.setArguments (args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getSupportedFormats () {
|
||||
// TODO Should we consider Attr.ENUM as well? Maybe for match_parent and wrap_content.
|
||||
return new int[] { Attr.DIMENSION };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View createEditorView (LayoutInflater inflater, ViewGroup parent) {
|
||||
this.binding = LayoutDimensionEditorBinding.inflate (inflater, parent, false);
|
||||
return this.binding.getRoot ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated (view, savedInstanceState);
|
||||
}
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.itsaky.androidide.fragments.attreditors;
|
||||
|
||||
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.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.itsaky.androidide.R;
|
||||
import com.itsaky.androidide.app.StudioApp;
|
||||
import com.itsaky.androidide.databinding.LayoutBaseAttrEditorBinding;
|
||||
import com.itsaky.androidide.models.XMLAttribute;
|
||||
import com.itsaky.androidide.utils.Logger;
|
||||
|
||||
/**
|
||||
* Base class for every attribute editor.
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public abstract class IAttrEditorFragment extends Fragment {
|
||||
|
||||
private XMLAttribute attribute;
|
||||
|
||||
protected static final String ATTRIBUTE_KEY = "xml_attribute";
|
||||
protected final Logger LOG = Logger.instance (getClass ().getSimpleName ());
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
LayoutBaseAttrEditorBinding binding = LayoutBaseAttrEditorBinding.inflate (inflater, container, false);
|
||||
binding.getRoot ().addView (createEditorView (inflater, binding.getRoot ()), generateEditorLayoutParams ());
|
||||
return binding.getRoot ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated (@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated (view, savedInstanceState);
|
||||
|
||||
if (getArguments () == null) {
|
||||
LOG.error ("No arguments found. Use IAttrEditorFragment#newInstance(..) to create these type of fragments");
|
||||
return;
|
||||
}
|
||||
|
||||
final var args = getArguments ();
|
||||
final var attribute = (XMLAttribute) args.getParcelable (ATTRIBUTE_KEY);
|
||||
|
||||
if (attribute == null) {
|
||||
throw new IllegalArgumentException ("How can we edit a null attribute?");
|
||||
}
|
||||
|
||||
validate (attribute);
|
||||
|
||||
this.attribute = attribute;
|
||||
}
|
||||
|
||||
protected ConstraintLayout.LayoutParams generateEditorLayoutParams () {
|
||||
final var params = new ConstraintLayout.LayoutParams (0, 0);
|
||||
params.topToBottom = R.id.editor_divider;
|
||||
params.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;
|
||||
params.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;
|
||||
params.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided attribute is valid for this editor or not.
|
||||
* If not, an {@link ValidationException} will be thrown.
|
||||
*
|
||||
* @param attribute The attribute to validate.
|
||||
* @return {@code true} if the attribute is valid, {@code false} otherwise.
|
||||
*/
|
||||
protected boolean validate (XMLAttribute attribute) {
|
||||
final var attrs = StudioApp.getInstance ().attrInfo ();
|
||||
final var attr = attrs.getAttribute (attribute.getAttributeName ());
|
||||
|
||||
if (attr == null) {
|
||||
throw new ValidationException ("Cannot find attribute with the given name: " + attribute.getAttributeName ());
|
||||
}
|
||||
|
||||
for (var format : getSupportedFormats ()) {
|
||||
if ((attr.format & format) != 0) {
|
||||
LOG.error ("Error validating given attribute", "attr: " + attr, "attribute: " + attribute);
|
||||
throw new ValidationException ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses are supposed to inflate the layout in this method.
|
||||
*
|
||||
* @param inflater The layout inflater. Same as passed in {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}.
|
||||
* @param parent The parent group to use when inflating the layout.
|
||||
* @return The created or inflated attribute editor view.
|
||||
*/
|
||||
protected abstract View createEditorView (LayoutInflater inflater, ViewGroup parent);
|
||||
|
||||
/**
|
||||
* Create a new instance of this attribute editor fragment.
|
||||
* TODO Instead of defining this in every subclass, can we use reflection to create instances by default?
|
||||
* How would it affect performance?
|
||||
* As of now, we only set arguments for the newly created fragment. So we can implement any generic method.
|
||||
*
|
||||
* @param attribute The attribute to be edited.
|
||||
* @return The new instance of this fragment.
|
||||
*/
|
||||
protected abstract IAttrEditorFragment newInstance (XMLAttribute attribute);
|
||||
|
||||
/**
|
||||
* Get the formats supported by this attribute editor.
|
||||
* This will be used to valid the attribute passed to this editor fragment.
|
||||
* in {@link #validate(XMLAttribute)}.
|
||||
*
|
||||
* @return The supported formats.
|
||||
*/
|
||||
protected abstract int[] getSupportedFormats ();
|
||||
|
||||
/**
|
||||
* An unchecked exception which is thrown if we fail to validate
|
||||
* the given attribute.
|
||||
*/
|
||||
protected static class ValidationException extends RuntimeException {
|
||||
|
||||
public ValidationException () {
|
||||
this("Given attribute is invalid.");
|
||||
}
|
||||
|
||||
public ValidationException (String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,10 +52,11 @@ public class AttrEditorSheet extends BottomSheetDialogFragment implements Simple
|
||||
|
||||
private IView selectedView;
|
||||
private LayoutAttrEditorSheetBinding binding;
|
||||
private final Logger LOG = Logger.instance ("AttrSheetEditor");
|
||||
|
||||
private OnViewDeletionFailedListener mDeletionFailedListener;
|
||||
|
||||
private static final Logger LOG = Logger.instance ("AttrBottomSheet");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView (@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
@@ -104,6 +105,11 @@ public class AttrEditorSheet extends BottomSheetDialogFragment implements Simple
|
||||
}
|
||||
|
||||
private void onAttrClick (LayoutAttrEditorSheetItemBinding binding, XMLAttribute attribute) {
|
||||
final var inflated = inflateAppropriateEditor (attribute);
|
||||
}
|
||||
|
||||
private View inflateAppropriateEditor (XMLAttribute attribute) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
package com.itsaky.androidide.models;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.itsaky.layoutinflater.IAttribute;
|
||||
@@ -29,7 +32,7 @@ import org.jetbrains.annotations.Contract;
|
||||
*
|
||||
* @author Akash Yadav
|
||||
*/
|
||||
public class XMLAttribute extends UiAttribute {
|
||||
public class XMLAttribute extends UiAttribute implements Parcelable {
|
||||
|
||||
/**
|
||||
* Is this attribute applied to any view?
|
||||
@@ -49,6 +52,26 @@ public class XMLAttribute extends UiAttribute {
|
||||
this.isApplied = isApplied;
|
||||
}
|
||||
|
||||
private XMLAttribute (@NonNull Parcel in) {
|
||||
this (in.readString (), in.readString (), in.readString (), in.readByte () != 0);
|
||||
}
|
||||
|
||||
public static final Creator<XMLAttribute> CREATOR = new Creator<XMLAttribute> () {
|
||||
@NonNull
|
||||
@Contract("_ -> new")
|
||||
@Override
|
||||
public XMLAttribute createFromParcel (Parcel in) {
|
||||
return new XMLAttribute (in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Contract(value = "_ -> new", pure = true)
|
||||
@Override
|
||||
public XMLAttribute[] newArray (int size) {
|
||||
return new XMLAttribute[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the given string as a value to this attribute.
|
||||
* This will set {@link #isApplied()} to return {@code true}.
|
||||
@@ -88,4 +111,17 @@ public class XMLAttribute extends UiAttribute {
|
||||
public static XMLAttribute newAndroidAttribute (String name) {
|
||||
return new XMLAttribute ("android", name, "", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel (@NonNull Parcel dest, int flags) {
|
||||
dest.writeString (getNamespace ());
|
||||
dest.writeString (getAttributeName ());
|
||||
dest.writeString (getValue ());
|
||||
dest.writeByte ((byte) (isApplied ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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 <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<!--Used as a base layout for attribute editor layouts-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/attr_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="middle"
|
||||
android:maxLines="1"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="layout_height" />
|
||||
|
||||
<View
|
||||
android:id="@+id/editor_divider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/attr_name" />
|
||||
|
||||
<!-- Actual editor will be added here after this -->
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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 <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/dimension_options"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/dimension_match"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/attr_val_match_parent"
|
||||
/>
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/dimension_wrap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/attr_val_wrap_content"
|
||||
/>
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:id="@+id/dimension_fixed"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/attr_val_fixed"
|
||||
/>
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/hint_new_attr_value"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/dimension_options">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Reference in New Issue
Block a user