diff options
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java')
-rw-r--r-- | mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java b/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java new file mode 100644 index 000000000..38c38a9eb --- /dev/null +++ b/mobile/android/base/java/org/mozilla/gecko/EditBookmarkDialog.java @@ -0,0 +1,252 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import org.mozilla.gecko.db.BrowserDB; +import org.mozilla.gecko.db.BrowserContract.Bookmarks; +import org.mozilla.gecko.util.ThreadUtils; +import org.mozilla.gecko.util.UIAsyncTask; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.database.Cursor; +import android.support.design.widget.Snackbar; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; + +/** + * A dialog that allows editing a bookmarks url, title, or keywords + * <p> + * Invoked by calling one of the {@link org.mozilla.gecko.EditBookmarkDialog#show(String)} + * methods. + */ +public class EditBookmarkDialog { + private final Context mContext; + + public EditBookmarkDialog(Context context) { + mContext = context; + } + + /** + * A private struct to make it easier to pass bookmark data across threads + */ + private class Bookmark { + final int id; + final String title; + final String url; + final String keyword; + + public Bookmark(int aId, String aTitle, String aUrl, String aKeyword) { + id = aId; + title = aTitle; + url = aUrl; + keyword = aKeyword; + } + } + + /** + * This text watcher to enable or disable the OK button if the dialog contains + * valid information. This class is overridden to do data checking on different fields. + * By itself, it always enables the button. + * + * Callers can also assign a paired partner to the TextWatcher, and callers will check + * that both are enabled before enabling the ok button. + */ + private class EditBookmarkTextWatcher implements TextWatcher { + // A stored reference to the dialog containing the text field being watched + protected AlertDialog mDialog; + + // A stored text watcher to do the real verification of a field + protected EditBookmarkTextWatcher mPairedTextWatcher; + + // Whether or not the ok button should be enabled. + protected boolean mEnabled = true; + + public EditBookmarkTextWatcher(AlertDialog aDialog) { + mDialog = aDialog; + } + + public void setPairedTextWatcher(EditBookmarkTextWatcher aTextWatcher) { + mPairedTextWatcher = aTextWatcher; + } + + public boolean isEnabled() { + return mEnabled; + } + + // Textwatcher interface + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // Disable if the we're disabled or the paired partner is disabled + boolean enabled = mEnabled && (mPairedTextWatcher == null || mPairedTextWatcher.isEnabled()); + mDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled); + } + + @Override + public void afterTextChanged(Editable s) {} + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + } + + /** + * A version of the EditBookmarkTextWatcher for the url field of the dialog. + * Only checks if the field is empty or not. + */ + private class LocationTextWatcher extends EditBookmarkTextWatcher { + public LocationTextWatcher(AlertDialog aDialog) { + super(aDialog); + } + + // Disables the ok button if the location field is empty. + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + mEnabled = (s.toString().trim().length() > 0); + super.onTextChanged(s, start, before, count); + } + } + + /** + * A version of the EditBookmarkTextWatcher for the keyword field of the dialog. + * Checks if the field has any (non leading or trailing) spaces. + */ + private class KeywordTextWatcher extends EditBookmarkTextWatcher { + public KeywordTextWatcher(AlertDialog aDialog) { + super(aDialog); + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + // Disable if the keyword contains spaces + mEnabled = (s.toString().trim().indexOf(' ') == -1); + super.onTextChanged(s, start, before, count); + } + } + + /** + * Show the Edit bookmark dialog for a particular url. If the url is bookmarked multiple times + * this will just edit the first instance it finds. + * + * @param url The url of the bookmark to edit. The dialog will look up other information like the id, + * current title, or keywords associated with this url. If the url isn't bookmarked, the + * dialog will fail silently. If the url is bookmarked multiple times, this will only show + * information about the first it finds. + */ + public void show(final String url) { + final ContentResolver cr = mContext.getContentResolver(); + final BrowserDB db = BrowserDB.from(mContext); + (new UIAsyncTask.WithoutParams<Bookmark>(ThreadUtils.getBackgroundHandler()) { + @Override + public Bookmark doInBackground() { + final Cursor cursor = db.getBookmarkForUrl(cr, url); + if (cursor == null) { + return null; + } + + Bookmark bookmark = null; + try { + cursor.moveToFirst(); + bookmark = new Bookmark(cursor.getInt(cursor.getColumnIndexOrThrow(Bookmarks._ID)), + cursor.getString(cursor.getColumnIndexOrThrow(Bookmarks.TITLE)), + cursor.getString(cursor.getColumnIndexOrThrow(Bookmarks.URL)), + cursor.getString(cursor.getColumnIndexOrThrow(Bookmarks.KEYWORD))); + } finally { + cursor.close(); + } + return bookmark; + } + + @Override + public void onPostExecute(Bookmark bookmark) { + if (bookmark == null) { + return; + } + + show(bookmark.id, bookmark.title, bookmark.url, bookmark.keyword); + } + }).execute(); + } + + /** + * Show the Edit bookmark dialog for a set of data. This will show the dialog whether + * a bookmark with this url exists or not, but the results will NOT be saved if the id + * is not a valid bookmark id. + * + * @param id The id of the bookmark to change. If there is no bookmark with this ID, the dialog + * will fail silently. + * @param title The initial title to show in the dialog + * @param url The initial url to show in the dialog + * @param keyword The initial keyword to show in the dialog + */ + public void show(final int id, final String title, final String url, final String keyword) { + final Context context = mContext; + + AlertDialog.Builder editPrompt = new AlertDialog.Builder(context); + final View editView = LayoutInflater.from(context).inflate(R.layout.bookmark_edit, null); + editPrompt.setTitle(R.string.bookmark_edit_title); + editPrompt.setView(editView); + + final EditText nameText = ((EditText) editView.findViewById(R.id.edit_bookmark_name)); + final EditText locationText = ((EditText) editView.findViewById(R.id.edit_bookmark_location)); + final EditText keywordText = ((EditText) editView.findViewById(R.id.edit_bookmark_keyword)); + nameText.setText(title); + locationText.setText(url); + keywordText.setText(keyword); + + final BrowserDB db = BrowserDB.from(mContext); + editPrompt.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int whichButton) { + (new UIAsyncTask.WithoutParams<Void>(ThreadUtils.getBackgroundHandler()) { + @Override + public Void doInBackground() { + String newUrl = locationText.getText().toString().trim(); + String newKeyword = keywordText.getText().toString().trim(); + + db.updateBookmark(context.getContentResolver(), id, newUrl, nameText.getText().toString(), newKeyword); + return null; + } + + @Override + public void onPostExecute(Void result) { + SnackbarBuilder.builder((Activity) context) + .message(R.string.bookmark_updated) + .duration(Snackbar.LENGTH_LONG) + .buildAndShow(); + } + }).execute(); + } + }); + + editPrompt.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int whichButton) { + // do nothing + } + }); + + final AlertDialog dialog = editPrompt.create(); + + // Create our TextWatchers + LocationTextWatcher locationTextWatcher = new LocationTextWatcher(dialog); + KeywordTextWatcher keywordTextWatcher = new KeywordTextWatcher(dialog); + + // Cross reference the TextWatchers + locationTextWatcher.setPairedTextWatcher(keywordTextWatcher); + keywordTextWatcher.setPairedTextWatcher(locationTextWatcher); + + // Add the TextWatcher Listeners + locationText.addTextChangedListener(locationTextWatcher); + keywordText.addTextChangedListener(keywordTextWatcher); + + dialog.show(); + } +} |