From 97bf89f44beea20d58ac7060fda2ff64132dd9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Barth=C3=A9l=C3=A9my?= Date: Thu, 21 May 2015 23:07:18 +0200 Subject: [PATCH 1/2] Add an optionnal name to the color items. The user can edit the name of a color item from the ColorDetailActivity. In the ColorItemAdapter, if a color item does not have a name then its hexadecimal code will be used. --- .../activities/ColorDetailActivity.java | 46 +++++++++++- .../activities/PaletteCreationActivity.java | 2 +- .../activities/PaletteDetailActivity.java | 2 +- .../adapters/ColorItemAdapter.java | 7 +- .../cameracolorpicker/data/ColorItem.java | 25 +++++++ .../cameracolorpicker/data/ColorItems.java | 14 +++- .../fragments/EditTextDialogFragment.java | 73 ++++++++++++++++--- .../src/main/res/menu/menu_color_detail.xml | 7 ++ .../app/src/main/res/values-fr/strings.xml | 5 +- .../app/src/main/res/values/strings.xml | 3 + 10 files changed, 165 insertions(+), 19 deletions(-) diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java index 579c73d..07fb3e0 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java @@ -15,6 +15,7 @@ import android.support.annotation.NonNull; import android.support.v4.content.FileProvider; import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -22,6 +23,8 @@ import android.widget.TextView; import android.widget.Toast; +import org.w3c.dom.Text; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; @@ -31,9 +34,11 @@ import fr.tvbarthel.apps.cameracolorpicker.data.ColorItem; import fr.tvbarthel.apps.cameracolorpicker.data.ColorItems; import fr.tvbarthel.apps.cameracolorpicker.fragments.DeleteColorDialogFragment; +import fr.tvbarthel.apps.cameracolorpicker.fragments.EditTextDialogFragment; import fr.tvbarthel.apps.cameracolorpicker.utils.ClipDatas; -public class ColorDetailActivity extends AppCompatActivity implements View.OnClickListener, DeleteColorDialogFragment.Callback { +public class ColorDetailActivity extends AppCompatActivity implements View.OnClickListener, + DeleteColorDialogFragment.Callback, EditTextDialogFragment.Callback { /** * A key for passing a color item as extra. @@ -77,6 +82,11 @@ public class ColorDetailActivity extends AppCompatActivity implements View.OnCli */ private static final String FILE_PROVIDER_AUTHORITY = "fr.tvbarthel.apps.cameracolorpicker.fileprovider"; + /** + * A request code to use in {@link EditTextDialogFragment#newInstance(int, int, int, int, int, String)}. + */ + private static final int REQUEST_CODE_EDIT_COLOR_ITEM_NAME = 15; + public static void startWithColorItem(Context context, ColorItem colorItem, View colorPreviewClicked, boolean canBeDeleted) { final boolean isActivity = context instanceof Activity; @@ -161,6 +171,13 @@ protected void onCreate(Bundle savedInstanceState) { final Rect startBounds = intent.getParcelableExtra(EXTRA_START_BOUNDS); mCanBeDeleted = intent.getBooleanExtra(EXTRA_CAN_BE_DELETED, true); + // Set the title of the activity with the name of the color, if not null. + if (!TextUtils.isEmpty(mColorItem.getName())) { + setTitle(mColorItem.getName()); + } else { + setTitle(mColorItem.getHexString()); + } + // Create a rect that will be used to retrieve the stop bounds. final Rect stopBounds = new Rect(); @@ -266,6 +283,13 @@ public boolean onOptionsItemSelected(MenuItem item) { finish(); } else if (id == R.id.menu_color_detail_action_share) { return handleActionShare(); + } else if (id == R.id.menu_color_detail_action_edit) { + EditTextDialogFragment.newInstance(REQUEST_CODE_EDIT_COLOR_ITEM_NAME, + R.string.activity_color_detail_edit_text_dialog_fragment_title, + R.string.activity_color_detail_edit_text_dialog_fragment_positive_button, + android.R.string.cancel, + mColorItem.getHexString(), + mColorItem.getName(), true).show(getSupportFragmentManager(), null); } return super.onOptionsItemSelected(item); @@ -300,6 +324,25 @@ public void onColorDeletionConfirmed(@NonNull ColorItem colorItemToDelete) { } } + @Override + public void onEditTextDialogFragmentPositiveButtonClick(int requestCode, String text) { + if (requestCode == REQUEST_CODE_EDIT_COLOR_ITEM_NAME) { + if (TextUtils.isEmpty(text)) { + setTitle(mColorItem.getHexString()); + } else { + setTitle(text); + } + + mColorItem.setName(text); + ColorItems.saveColorItem(this, mColorItem); + } + } + + @Override + public void onEditTextDialogFragmentNegativeButtonClick(int requestCode) { + // nothing to do here. + } + protected void clipColor(int labelResourceId, CharSequence colorString) { ClipDatas.clipPainText(this, getString(labelResourceId), colorString); @@ -379,5 +422,4 @@ private boolean handleActionShare() { return handled; } - } diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteCreationActivity.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteCreationActivity.java index b2f2cf5..454ab1e 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteCreationActivity.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteCreationActivity.java @@ -102,7 +102,7 @@ public void onClick(View v) { R.string.activity_palette_creation_edit_text_dialog_fragment_title, R.string.activity_palette_creation_edit_text_dialog_fragment_positive_button, android.R.string.cancel, - R.string.activity_palette_creation_edit_text_dialog_fragment_hint, + getString(R.string.activity_palette_creation_edit_text_dialog_fragment_hint), null); editTextDialogFragment.show(getSupportFragmentManager(), null); } diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java index e6404dd..70b7bd0 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java @@ -295,7 +295,7 @@ private boolean handleActionEditName() { R.string.activity_palette_detail_edit_palette_name_dialog_title, R.string.activity_palette_detail_edit_palette_name_dialog_positive_action, android.R.string.cancel, - R.string.activity_palette_detail_edit_palette_name_dialog_hint, + getString(R.string.activity_palette_detail_edit_palette_name_dialog_hint), mPalette.getName()).show(getSupportFragmentManager(), null); return true; } diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/adapters/ColorItemAdapter.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/adapters/ColorItemAdapter.java index aea99f4..e4c7a34 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/adapters/ColorItemAdapter.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/adapters/ColorItemAdapter.java @@ -2,6 +2,7 @@ import android.content.Context; import android.graphics.PorterDuff; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -59,7 +60,11 @@ protected View createView(ViewGroup parent) { protected void bindViewHolder(ViewHolder viewHolder, int position) { final ColorItem colorItem = getItem(position); viewHolder.mColorPreview.getBackground().setColorFilter(colorItem.getColor(), PorterDuff.Mode.MULTIPLY); - viewHolder.mColorText.setText(colorItem.getHexString()); + if (!TextUtils.isEmpty(colorItem.getName())) { + viewHolder.mColorText.setText(colorItem.getName()); + } else { + viewHolder.mColorText.setText(colorItem.getHexString()); + } } /** diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItem.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItem.java index 29018dd..5d1fea6 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItem.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItem.java @@ -19,6 +19,11 @@ public class ColorItem implements Parcelable { */ protected int mColor; + /** + * An optional name that the user can give to a color. + */ + protected String mName; + /** * A long representing the creation time of the color. (In milliseconds). */ @@ -63,6 +68,7 @@ private ColorItem(Parcel in) { this.mId = in.readLong(); this.mColor = in.readInt(); this.mCreationTime = in.readLong(); + this.mName = in.readString(); } /** @@ -154,6 +160,24 @@ public String getHsvString() { return mHsvString; } + /** + * Get the name of the color. + * + * @return the name of the color. + */ + public String getName() { + return mName; + } + + /** + * Set the name of the color. + * + * @param name the new name of the color. + */ + public void setName(String name) { + mName = name; + } + /** * Make a human readable representation of the hexadecimal value of a color. * @@ -197,6 +221,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeLong(this.mId); dest.writeInt(this.mColor); dest.writeLong(this.mCreationTime); + dest.writeString(this.mName); } /** diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItems.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItems.java index edb6794..503f19e 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItems.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/data/ColorItems.java @@ -138,7 +138,17 @@ public static boolean saveColorItem(Context context, ColorItem colorToSave) { final List savedColorsItems = getSavedColorItems(context); final SharedPreferences.Editor editor = getPreferences(context).edit(); final List colorItems = new ArrayList<>(savedColorsItems.size() + 1); - colorItems.addAll(savedColorsItems); + + // Add the saved color items except the one with the same ID. It will be overridden. + final int size = savedColorsItems.size(); + for (int i = 0; i < size; i++) { + final ColorItem candidate = savedColorsItems.get(i); + if (candidate.getId() != colorToSave.getId()) { + colorItems.add(candidate); + } + } + + // Add the new color to save colorItems.add(colorToSave); editor.putString(KEY_SAVED_COLOR_ITEMS, GSON.toJson(colorItems)); @@ -146,6 +156,8 @@ public static boolean saveColorItem(Context context, ColorItem colorToSave) { return editor.commit(); } + + /** * Delete a {@link fr.tvbarthel.apps.cameracolorpicker.data.ColorItem}. * diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/fragments/EditTextDialogFragment.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/fragments/EditTextDialogFragment.java index a8cb3d1..8ab693c 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/fragments/EditTextDialogFragment.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/fragments/EditTextDialogFragment.java @@ -55,13 +55,18 @@ public class EditTextDialogFragment extends DialogFragment { /** * A key for passing the resource id of the hint text. */ - private static final String ARG_EDIT_TEXT_HINT_RESOURCE_ID = "EditTextDialogFragment.Args.ARG_EDIT_TEXT_HINT_RESOURCE_ID"; + private static final String ARG_EDIT_TEXT_HINT = "EditTextDialogFragment.Args.ARG_EDIT_TEXT_HINT"; /** * A key for passing the initial text value. */ private static final String ARG_EDIT_TEXT_INITIAL_TEXT = "EditTextDialogFragment.Args.ARG_EDIT_TEXT_INITIAL_TEXT"; + /** + * A key for allowing empty string. + */ + private static final String ARG_ALLOW_EMPTY_STRING = "EditTextDialogFragment.Args.ARG_ALLOW_EMPTY_STRING"; + /** * Create a new instance of a {@link EditTextDialogFragment} to ask the user to define the name of a {@link Palette}. * @@ -69,7 +74,7 @@ public class EditTextDialogFragment extends DialogFragment { * @param titleResourceId the resource id of the title. * @param positiveButtonResourceId the resource id of the positive button. * @param negativeButtonResourceId the resource id of the negative button. - * @param editTextHintResourceId the resource id of the edit text hint. + * @param editTextHint the edit text hint. * @param editTextInitialText the initial text of the edit text. * @return the newly created {@link EditTextDialogFragment}. */ @@ -77,16 +82,40 @@ public static EditTextDialogFragment newInstance(int requestCode, @StringRes int titleResourceId, @StringRes int positiveButtonResourceId, @StringRes int negativeButtonResourceId, - @StringRes int editTextHintResourceId, + String editTextHint, String editTextInitialText) { + return newInstance(requestCode, titleResourceId, positiveButtonResourceId, + negativeButtonResourceId, editTextHint, editTextInitialText, false); + } + + /** + * Create a new instance of a {@link EditTextDialogFragment} to ask the user to define the name of a {@link Palette}. + * + * @param requestCode the request code + * @param titleResourceId the resource id of the title. + * @param positiveButtonResourceId the resource id of the positive button. + * @param negativeButtonResourceId the resource id of the negative button. + * @param editTextHint the edit text hint. + * @param editTextInitialText the initial text of the edit text. + * @param allowEmptyString if true empty string will be allowed, otherwise a 'nope' animation will be played if the user tries to validate an empty string. + * @return the newly created {@link EditTextDialogFragment}. + */ + public static EditTextDialogFragment newInstance(int requestCode, + @StringRes int titleResourceId, + @StringRes int positiveButtonResourceId, + @StringRes int negativeButtonResourceId, + String editTextHint, + String editTextInitialText, + boolean allowEmptyString) { final EditTextDialogFragment instance = new EditTextDialogFragment(); final Bundle args = new Bundle(); args.putInt(ARG_REQUEST_CODE, requestCode); args.putInt(ARG_TITLE_RESOURCE_ID, titleResourceId); args.putInt(ARG_POSITIVE_BUTTON_RESOURCE_ID, positiveButtonResourceId); args.putInt(ARG_NEGATIVE_BUTTON_RESOURCE_ID, negativeButtonResourceId); - args.putInt(ARG_EDIT_TEXT_HINT_RESOURCE_ID, editTextHintResourceId); + args.putString(ARG_EDIT_TEXT_HINT, editTextHint); args.putString(ARG_EDIT_TEXT_INITIAL_TEXT, editTextInitialText); + args.putBoolean(ARG_ALLOW_EMPTY_STRING, allowEmptyString); instance.setArguments(args); return instance; } @@ -96,12 +125,27 @@ public static EditTextDialogFragment newInstance(int requestCode, */ private Callback mCallback; + /** + * The {@link EditText} + */ private EditText mEditText; + /** + * An {@link ObjectAnimator} for playing a nope animation when the users tries to validate an empty string, + * and mAllowEmptyString is false. + */ private ObjectAnimator mNopeAnimator; + /** + * The request code. + */ private int mRequestCode; + /** + * If true the users can validate empty string. + */ + private boolean mAllowEmptyString; + /** * Default Constructor. *

@@ -138,17 +182,18 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { // Extract the arguments mRequestCode = args.getInt(ARG_REQUEST_CODE); + mAllowEmptyString= args.getBoolean(ARG_ALLOW_EMPTY_STRING); final int titleResourceId = args.getInt(ARG_TITLE_RESOURCE_ID); final int positiveButtonResourceId = args.getInt(ARG_POSITIVE_BUTTON_RESOURCE_ID); final int negativeButtonResourceId = args.getInt(ARG_NEGATIVE_BUTTON_RESOURCE_ID); - final int editTextHintResourceId = args.getInt(ARG_EDIT_TEXT_HINT_RESOURCE_ID); + final String editTextHint = args.getString(ARG_EDIT_TEXT_HINT); final String editTextInitialText = args.getString(ARG_EDIT_TEXT_INITIAL_TEXT); final Context context = getActivity(); final View view = LayoutInflater.from(context).inflate(R.layout.fragment_dialog_edit_text, null); mEditText = (EditText) view.findViewById(R.id.fragment_dialog_edit_text_edit_text); - mEditText.setHint(editTextHintResourceId); + mEditText.setHint(editTextHint); mEditText.setText(editTextInitialText); mNopeAnimator = Views.nopeAnimation(mEditText, mEditText.getPaddingLeft()); @@ -156,8 +201,8 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { builder.setView(view) .setTitle(titleResourceId) .setCancelable(true) - // We don't want the positive button to always dismiss the alert dialog. - // The onClickListener is set in an OnShowListener bellow. + // We don't want the positive button to always dismiss the alert dialog. + // The onClickListener is set in an OnShowListener bellow. .setPositiveButton(positiveButtonResourceId, null) .setNegativeButton(negativeButtonResourceId, new DialogInterface.OnClickListener() { @Override @@ -199,7 +244,7 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { private void handlePositiveClick() { final String text = mEditText.getText().toString(); - if (TextUtils.isEmpty(text)) { + if (TextUtils.isEmpty(text) && !mAllowEmptyString) { if (mNopeAnimator.isRunning()) { mNopeAnimator.cancel(); } @@ -240,13 +285,17 @@ private void ensureSaneArgs(Bundle args) { throw new IllegalArgumentException("Missing negative button resource id. Please use EditTextDialogFragment#newInstance()"); } - if (!args.containsKey(ARG_EDIT_TEXT_HINT_RESOURCE_ID)) { + if (!args.containsKey(ARG_EDIT_TEXT_HINT)) { throw new IllegalArgumentException("Missing edit text hint resource id. Please use EditTextDialogFragment#newInstance()"); } if (!args.containsKey(ARG_EDIT_TEXT_INITIAL_TEXT)) { throw new IllegalArgumentException("Missing edit text initial text. Please use EditTextDialogFragment#newInstance()"); } + + if (!args.containsKey(ARG_ALLOW_EMPTY_STRING)) { + throw new IllegalArgumentException("Missing edit text initial text. Please use EditTextDialogFragment#newInstance()"); + } } /** @@ -257,7 +306,7 @@ public interface Callback { /** * Called when the user has just clicked on the positive button. * - * @param requestCode the request code passed in the {@link EditTextDialogFragment#newInstance(int, int, int, int, int, String)} method. + * @param requestCode the request code passed in the {@link EditTextDialogFragment#newInstance(int, int, int, int, String, String)} method. * @param text the text of the edit text. */ void onEditTextDialogFragmentPositiveButtonClick(int requestCode, String text); @@ -265,7 +314,7 @@ public interface Callback { /** * Called when the user has just clicked the negative button. * - * @param requestCode the request code passed in the {@link EditTextDialogFragment#newInstance(int, int, int, int, int, String)} method. + * @param requestCode the request code passed in the {@link EditTextDialogFragment#newInstance(int, int, int, int, String, String)} method. */ void onEditTextDialogFragmentNegativeButtonClick(int requestCode); } diff --git a/CameraColorPicker/app/src/main/res/menu/menu_color_detail.xml b/CameraColorPicker/app/src/main/res/menu/menu_color_detail.xml index e1c8613..5e66dfc 100644 --- a/CameraColorPicker/app/src/main/res/menu/menu_color_detail.xml +++ b/CameraColorPicker/app/src/main/res/menu/menu_color_detail.xml @@ -10,6 +10,13 @@ android:orderInCategory="10" app:showAsAction="ifRoom" /> + + Choisir une couleur + Couleur enregistrée Détail - Couleur enregistrée + Editer le nom de la couleur + Editer Contenu et Licenses @@ -55,6 +57,7 @@ Partager + Editer Supprimer diff --git a/CameraColorPicker/app/src/main/res/values/strings.xml b/CameraColorPicker/app/src/main/res/values/strings.xml index 11fabae..78d09c4 100644 --- a/CameraColorPicker/app/src/main/res/values/strings.xml +++ b/CameraColorPicker/app/src/main/res/values/strings.xml @@ -19,6 +19,8 @@ Detail + Edit the name of the color + Edit Content and Licenses @@ -57,6 +59,7 @@ Share + Edit Delete From fb385748b1f6d12c9b4a90711eef47bb9052ee64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Barth=C3=A9l=C3=A9my?= Date: Sun, 31 May 2015 18:16:13 +0200 Subject: [PATCH 2/2] Fix the edition of the color items. Changes of the name of a ColorItem was not reflected in the PaletteDetailActivity. Once a ColorItem has been added to a Palette, it exists on its own, meaning that any changes on the original ColorPalette (e.g. name) won't affect the ColorItem in the Palette and vice versa. --- .../activities/ColorDetailActivity.java | 73 ++++++++++++++----- .../activities/PaletteDetailActivity.java | 65 +++++++++++++++-- .../views/ColorItemListPage.java | 5 +- 3 files changed, 114 insertions(+), 29 deletions(-) diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java index 07fb3e0..62d2294 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/ColorDetailActivity.java @@ -12,6 +12,7 @@ import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; +import android.os.PersistableBundle; import android.support.annotation.NonNull; import android.support.v4.content.FileProvider; import android.support.v7.app.AppCompatActivity; @@ -29,10 +30,13 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.List; import fr.tvbarthel.apps.cameracolorpicker.R; import fr.tvbarthel.apps.cameracolorpicker.data.ColorItem; import fr.tvbarthel.apps.cameracolorpicker.data.ColorItems; +import fr.tvbarthel.apps.cameracolorpicker.data.Palette; +import fr.tvbarthel.apps.cameracolorpicker.data.Palettes; import fr.tvbarthel.apps.cameracolorpicker.fragments.DeleteColorDialogFragment; import fr.tvbarthel.apps.cameracolorpicker.fragments.EditTextDialogFragment; import fr.tvbarthel.apps.cameracolorpicker.utils.ClipDatas; @@ -51,11 +55,10 @@ public class ColorDetailActivity extends AppCompatActivity implements View.OnCli private static final String EXTRA_START_BOUNDS = "ColorDetailActivity.Extras.EXTRA_START_BOUNDS"; /** - * A key for knowing if the {@link ColorItem} can be deleted. - *

- * If the color item can not be deleted, the delete action will be removed from the menu. + * A key for passing an optional palette that is associated with the color item displayed. + * */ - private static final String EXTRA_CAN_BE_DELETED = "ColorDetailActivity.Extras.EXTRA_CAN_BE_DELETED"; + private static final String EXTRA_PALETTE = "ColorDetailActivity.Extras.EXTRA_PALETTE"; /** * The quality of the image compressed before sharing. @@ -83,12 +86,17 @@ public class ColorDetailActivity extends AppCompatActivity implements View.OnCli private static final String FILE_PROVIDER_AUTHORITY = "fr.tvbarthel.apps.cameracolorpicker.fileprovider"; /** - * A request code to use in {@link EditTextDialogFragment#newInstance(int, int, int, int, int, String)}. + * A request code to use in {@link EditTextDialogFragment#newInstance(int, int, int, int, String, String, boolean)}. */ private static final int REQUEST_CODE_EDIT_COLOR_ITEM_NAME = 15; - public static void startWithColorItem(Context context, ColorItem colorItem, View colorPreviewClicked, - boolean canBeDeleted) { + public static void startWithColorItem(Context context, ColorItem colorItem, + View colorPreviewClicked){ + startWithColorItem(context, colorItem, colorPreviewClicked, null); + } + + public static void startWithColorItem(Context context, ColorItem colorItem, + View colorPreviewClicked, Palette palette) { final boolean isActivity = context instanceof Activity; final Rect startBounds = new Rect(); colorPreviewClicked.getGlobalVisibleRect(startBounds); @@ -96,7 +104,7 @@ public static void startWithColorItem(Context context, ColorItem colorItem, View final Intent intent = new Intent(context, ColorDetailActivity.class); intent.putExtra(EXTRA_COLOR_ITEM, colorItem); intent.putExtra(EXTRA_START_BOUNDS, startBounds); - intent.putExtra(EXTRA_CAN_BE_DELETED, canBeDeleted); + intent.putExtra(EXTRA_PALETTE, palette); if (!isActivity) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -147,11 +155,9 @@ public static void startWithColorItem(Context context, ColorItem colorItem, View private ColorItem mColorItem; /** - * A boolean for knowing if the {@link ColorItem} can be deleted or not. - *

- * If false, the delete action will be removed from the menu. + * An optional {@link Palette} that is associated with the {@link ColorItem}. */ - private boolean mCanBeDeleted; + private Palette mPalette; @Override protected void onCreate(Bundle savedInstanceState) { @@ -162,14 +168,19 @@ protected void onCreate(Bundle savedInstanceState) { // ensure correct extras. final Intent intent = getIntent(); if (!intent.hasExtra(EXTRA_COLOR_ITEM) || !intent.hasExtra(EXTRA_START_BOUNDS) - || !intent.hasExtra(EXTRA_CAN_BE_DELETED)) { + || !intent.hasExtra(EXTRA_PALETTE)) { throw new IllegalStateException("Missing extras. Please use startWithColorItem."); } // Retrieve the extras. - mColorItem = intent.getParcelableExtra(EXTRA_COLOR_ITEM); final Rect startBounds = intent.getParcelableExtra(EXTRA_START_BOUNDS); - mCanBeDeleted = intent.getBooleanExtra(EXTRA_CAN_BE_DELETED, true); + if (savedInstanceState == null) { + mColorItem = intent.getParcelableExtra(EXTRA_COLOR_ITEM); + mPalette = intent.getParcelableExtra(EXTRA_PALETTE); + } else { + mColorItem = savedInstanceState.getParcelable(EXTRA_COLOR_ITEM); + mPalette = savedInstanceState.getParcelable(EXTRA_PALETTE); + } // Set the title of the activity with the name of the color, if not null. if (!TextUtils.isEmpty(mColorItem.getName())) { @@ -258,11 +269,19 @@ protected void onPause() { hideToast(); } + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(EXTRA_COLOR_ITEM, mColorItem); + outState.putParcelable(EXTRA_PALETTE, mPalette); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_color_detail, menu); - if (!mCanBeDeleted) { + if (mPalette != null) { + // A color associated with a palette can't be deleted. menu.removeItem(R.id.menu_color_detail_action_delete); } return true; @@ -327,14 +346,34 @@ public void onColorDeletionConfirmed(@NonNull ColorItem colorItemToDelete) { @Override public void onEditTextDialogFragmentPositiveButtonClick(int requestCode, String text) { if (requestCode == REQUEST_CODE_EDIT_COLOR_ITEM_NAME) { + // Update the title of the activity. if (TextUtils.isEmpty(text)) { setTitle(mColorItem.getHexString()); } else { setTitle(text); } + // Set the new name. mColorItem.setName(text); - ColorItems.saveColorItem(this, mColorItem); + + // Persist the change. + if (mPalette == null) { + // The color item is a standalone color. + // It's not associated with a palette. + // Just save the color item. + ColorItems.saveColorItem(this, mColorItem); + } else { + // The color item is associated with a palette. + // Edit and save the palette. + final List colorItems = mPalette.getColors(); + for (ColorItem candidate : colorItems) { + if (candidate.getId() == mColorItem.getId()) { + candidate.setName(text); + break; + } + } + Palettes.saveColorPalette(this, mPalette); + } } } diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java index 70b7bd0..7e3b143 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/activities/PaletteDetailActivity.java @@ -13,6 +13,7 @@ import android.graphics.RectF; import android.net.Uri; import android.os.Bundle; +import android.os.PersistableBundle; import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.v4.content.FileProvider; @@ -129,6 +130,11 @@ public static void startWithColorPalette(Context context, Palette palette, View */ private Toast mToast; + /** + * A {@link fr.tvbarthel.apps.cameracolorpicker.data.Palettes.OnPaletteChangeListener} for updating the palette when the user change the name for instance. + */ + private Palettes.OnPaletteChangeListener mOnPaletteChangeListener; + @Override public void onCreate(Bundle savedInstanceState) { @@ -144,7 +150,11 @@ public void onCreate(Bundle savedInstanceState) { } // Retrieve the extras. - mPalette = intent.getParcelableExtra(EXTRA_COLOR_PALETTE); + if (savedInstanceState == null) { + mPalette = intent.getParcelableExtra(EXTRA_COLOR_PALETTE); + } else { + mPalette = savedInstanceState.getParcelable(EXTRA_COLOR_PALETTE); + } final Rect startBounds = intent.getParcelableExtra(EXTRA_START_BOUNDS); setTitle(mPalette.getName()); @@ -164,7 +174,7 @@ public void onCreate(Bundle savedInstanceState) { public void onItemClick(AdapterView parent, View view, int position, long id) { final ColorItem colorItem = adapter.getItem(position); ColorDetailActivity.startWithColorItem(view.getContext(), colorItem, - view.findViewById(R.id.row_color_item_preview), false); + view.findViewById(R.id.row_color_item_preview), mPalette); } }); @@ -230,6 +240,39 @@ public void onAnimationRepeat(Animator animation) { } }); } + + mOnPaletteChangeListener = new Palettes.OnPaletteChangeListener() { + @Override + public void onColorPaletteChanged(List palettes) { + Palette newPalette = null; + for (Palette candidate : palettes) { + if (candidate.getId() == mPalette.getId()) { + newPalette = candidate; + break; + } + } + + if (newPalette == null) { + // The palette opened is not in the saved palettes. + // It has been deleted, just finish the activity. + finish(); + } else { + // Reload the palette. + mPalette = newPalette; + setTitle(mPalette.getName()); + adapter.clear(); + adapter.addAll(mPalette.getColors()); + } + } + }; + + Palettes.registerListener(this, mOnPaletteChangeListener); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putParcelable(EXTRA_COLOR_PALETTE, mPalette); } @Override @@ -238,6 +281,12 @@ protected void onPause() { super.onPause(); } + @Override + protected void onDestroy() { + Palettes.unregisterListener(this, mOnPaletteChangeListener); + super.onDestroy(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. @@ -267,18 +316,18 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onPaletteDeletionConfirmed(@NonNull Palette paletteToDelete) { - if (Palettes.deleteColorPalette(this, paletteToDelete)) { - finish(); - } + // Delete the palette + // Note: we don't finish the activity, it will be finished in mOnPaletteChangeListener. + Palettes.deleteColorPalette(this, paletteToDelete); } @Override public void onEditTextDialogFragmentPositiveButtonClick(int requestCode, String text) { if (!mPalette.getName().equals(text)) { + // Set the new name and save the palette. + // Note: we don't update the UI there, it will be updated in mOnPaletteChangeListener. mPalette.setName(text); - if (Palettes.saveColorPalette(this, mPalette)) { - setTitle(text); - } + Palettes.saveColorPalette(this, mPalette); } } diff --git a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/views/ColorItemListPage.java b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/views/ColorItemListPage.java index 69405cc..1cb65ec 100644 --- a/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/views/ColorItemListPage.java +++ b/CameraColorPicker/app/src/main/java/fr/tvbarthel/apps/cameracolorpicker/views/ColorItemListPage.java @@ -15,8 +15,6 @@ import android.widget.ListView; import android.widget.Toast; -import com.melnykov.fab.FloatingActionButton; - import java.util.List; import fr.tvbarthel.apps.cameracolorpicker.R; @@ -114,7 +112,7 @@ private void init(Context context) { public void onItemClick(AdapterView parent, View view, int position, long id) { final ColorItem colorItem = mColorItemAdapter.getItem(position); ColorDetailActivity.startWithColorItem(view.getContext(), colorItem, - view.findViewById(R.id.row_color_item_preview), true); + view.findViewById(R.id.row_color_item_preview)); } }); @@ -175,7 +173,6 @@ public void onActivityDestroyed(Activity activity) { } - /** * Hide the current {@link android.widget.Toast}. */