| |
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- |
| |
2 * This Source Code Form is subject to the terms of the Mozilla Public |
| |
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
| |
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
5 |
| |
6 package org.mozilla.gecko; |
| |
7 |
| |
8 import org.mozilla.gecko.db.BrowserContract.Bookmarks; |
| |
9 import org.mozilla.gecko.db.BrowserDB; |
| |
10 import org.mozilla.gecko.util.ThreadUtils; |
| |
11 import org.mozilla.gecko.util.UiAsyncTask; |
| |
12 |
| |
13 import android.content.Context; |
| |
14 import android.app.AlertDialog; |
| |
15 import android.content.DialogInterface; |
| |
16 import android.database.Cursor; |
| |
17 import android.text.Editable; |
| |
18 import android.text.TextWatcher; |
| |
19 import android.view.LayoutInflater; |
| |
20 import android.view.View; |
| |
21 import android.widget.EditText; |
| |
22 import android.widget.Toast; |
| |
23 |
| |
24 /** |
| |
25 * A dialog that allows editing a bookmarks url, title, or keywords |
| |
26 * <p> |
| |
27 * Invoked by calling one of the {@link org.mozilla.gecko.EditBookmarkDialog.show} |
| |
28 * methods. |
| |
29 */ |
| |
30 public class EditBookmarkDialog { |
| |
31 private static final String LOGTAG = "GeckoEditBookmarkDialog"; |
| |
32 private Context mContext; |
| |
33 |
| |
34 public EditBookmarkDialog(Context context) { |
| |
35 mContext = context; |
| |
36 } |
| |
37 |
| |
38 /** |
| |
39 * A private struct to make it easier to pass bookmark data across threads |
| |
40 */ |
| |
41 private class Bookmark { |
| |
42 int id; |
| |
43 String title; |
| |
44 String url; |
| |
45 String keyword; |
| |
46 |
| |
47 public Bookmark(int aId, String aTitle, String aUrl, String aKeyword) { |
| |
48 id = aId; |
| |
49 title = aTitle; |
| |
50 url = aUrl; |
| |
51 keyword = aKeyword; |
| |
52 } |
| |
53 } |
| |
54 |
| |
55 /** |
| |
56 * This text watcher to enable or disable the OK button if the dialog contains |
| |
57 * valid information. This class is overridden to do data checking diffferent fields. |
| |
58 * By itself, it always enables the button. |
| |
59 * |
| |
60 * Callers can also assing a paired partner to the TextWatcher, and callers will check |
| |
61 * that both are enabled before enabling the ok button. |
| |
62 */ |
| |
63 private class EditBookmarkTextWatcher implements TextWatcher { |
| |
64 // A stored reference to the dialog containing the text field being watched |
| |
65 protected AlertDialog mDialog; |
| |
66 |
| |
67 // A stored text watcher to do the real verification of a field |
| |
68 protected EditBookmarkTextWatcher mPairedTextWatcher; |
| |
69 |
| |
70 // Whether or not the ok button should be enabled. |
| |
71 protected boolean mEnabled = true; |
| |
72 |
| |
73 public EditBookmarkTextWatcher(AlertDialog aDialog) { |
| |
74 mDialog = aDialog; |
| |
75 } |
| |
76 |
| |
77 public void setPairedTextWatcher(EditBookmarkTextWatcher aTextWatcher) { |
| |
78 mPairedTextWatcher = aTextWatcher; |
| |
79 } |
| |
80 |
| |
81 public boolean isEnabled() { |
| |
82 return mEnabled; |
| |
83 } |
| |
84 |
| |
85 // Textwatcher interface |
| |
86 @Override |
| |
87 public void onTextChanged(CharSequence s, int start, int before, int count) { |
| |
88 // Disable if the we're disabled or the paired partner is disabled |
| |
89 boolean enabled = mEnabled && (mPairedTextWatcher == null || mPairedTextWatcher.isEnabled()); |
| |
90 mDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled); |
| |
91 } |
| |
92 |
| |
93 @Override |
| |
94 public void afterTextChanged(Editable s) {} |
| |
95 @Override |
| |
96 public void beforeTextChanged(CharSequence s, int start, int count, int after) {} |
| |
97 } |
| |
98 |
| |
99 /** |
| |
100 * A version of the EditBookmarkTextWatcher for the url field of the dialog. |
| |
101 * Only checks if the field is empty or not. |
| |
102 */ |
| |
103 private class LocationTextWatcher extends EditBookmarkTextWatcher { |
| |
104 public LocationTextWatcher(AlertDialog aDialog) { |
| |
105 super(aDialog); |
| |
106 } |
| |
107 |
| |
108 // Disables the ok button if the location field is empty. |
| |
109 @Override |
| |
110 public void onTextChanged(CharSequence s, int start, int before, int count) { |
| |
111 mEnabled = (s.toString().trim().length() > 0); |
| |
112 super.onTextChanged(s, start, before, count); |
| |
113 } |
| |
114 } |
| |
115 |
| |
116 /** |
| |
117 * A version of the EditBookmarkTextWatcher for the keyword field of the dialog. |
| |
118 * Checks if the field has any (non leading or trailing) spaces. |
| |
119 */ |
| |
120 private class KeywordTextWatcher extends EditBookmarkTextWatcher { |
| |
121 public KeywordTextWatcher(AlertDialog aDialog) { |
| |
122 super(aDialog); |
| |
123 } |
| |
124 |
| |
125 @Override |
| |
126 public void onTextChanged(CharSequence s, int start, int before, int count) { |
| |
127 // Disable if the keyword contains spaces |
| |
128 mEnabled = (s.toString().trim().indexOf(' ') == -1); |
| |
129 super.onTextChanged(s, start, before, count); |
| |
130 } |
| |
131 } |
| |
132 |
| |
133 /** |
| |
134 * Show the Edit bookmark dialog for a particular url. If the url is bookmarked multiple times |
| |
135 * this will just edit the first instance it finds. |
| |
136 * |
| |
137 * @param url The url of the bookmark to edit. The dialog will look up other information like the id, |
| |
138 * current title, or keywords associated with this url. If the url isn't bookmarked, the |
| |
139 * dialog will fail silently. If the url is bookmarked multiple times, this will only show |
| |
140 * information about the first it finds. |
| |
141 */ |
| |
142 public void show(final String url) { |
| |
143 (new UiAsyncTask<Void, Void, Bookmark>(ThreadUtils.getBackgroundHandler()) { |
| |
144 @Override |
| |
145 public Bookmark doInBackground(Void... params) { |
| |
146 Cursor cursor = BrowserDB.getBookmarkForUrl(mContext.getContentResolver(), url); |
| |
147 if (cursor == null) { |
| |
148 return null; |
| |
149 } |
| |
150 |
| |
151 Bookmark bookmark = null; |
| |
152 try { |
| |
153 cursor.moveToFirst(); |
| |
154 bookmark = new Bookmark(cursor.getInt(cursor.getColumnIndexOrThrow(Bookmarks._ID)), |
| |
155 cursor.getString(cursor.getColumnIndexOrThrow(Bookmarks.TITLE)), |
| |
156 cursor.getString(cursor.getColumnIndexOrThrow(Bookmarks.URL)), |
| |
157 cursor.getString(cursor.getColumnIndexOrThrow(Bookmarks.KEYWORD))); |
| |
158 } finally { |
| |
159 cursor.close(); |
| |
160 } |
| |
161 return bookmark; |
| |
162 } |
| |
163 |
| |
164 @Override |
| |
165 public void onPostExecute(Bookmark bookmark) { |
| |
166 if (bookmark == null) |
| |
167 return; |
| |
168 |
| |
169 show(bookmark.id, bookmark.title, bookmark.url, bookmark.keyword); |
| |
170 } |
| |
171 }).execute(); |
| |
172 } |
| |
173 |
| |
174 /** |
| |
175 * Show the Edit bookmark dialog for a set of data. This will show the dialog whether |
| |
176 * a bookmark with this url exists or not, but the results will NOT be saved if the id |
| |
177 * is not a valid bookmark id. |
| |
178 * |
| |
179 * @param id The id of the bookmark to change. If there is no bookmark with this ID, the dialog |
| |
180 * will fail silently. |
| |
181 * @param title The initial title to show in the dialog |
| |
182 * @param url The initial url to show in the dialog |
| |
183 * @param keyword The initial keyword to show in the dialog |
| |
184 */ |
| |
185 public void show(final int id, final String title, final String url, final String keyword) { |
| |
186 AlertDialog.Builder editPrompt = new AlertDialog.Builder(mContext); |
| |
187 final View editView = LayoutInflater.from(mContext).inflate(R.layout.bookmark_edit, null); |
| |
188 editPrompt.setTitle(R.string.bookmark_edit_title); |
| |
189 editPrompt.setView(editView); |
| |
190 |
| |
191 final EditText nameText = ((EditText) editView.findViewById(R.id.edit_bookmark_name)); |
| |
192 final EditText locationText = ((EditText) editView.findViewById(R.id.edit_bookmark_location)); |
| |
193 final EditText keywordText = ((EditText) editView.findViewById(R.id.edit_bookmark_keyword)); |
| |
194 nameText.setText(title); |
| |
195 locationText.setText(url); |
| |
196 keywordText.setText(keyword); |
| |
197 |
| |
198 editPrompt.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { |
| |
199 @Override |
| |
200 public void onClick(DialogInterface dialog, int whichButton) { |
| |
201 (new UiAsyncTask<Void, Void, Void>(ThreadUtils.getBackgroundHandler()) { |
| |
202 @Override |
| |
203 public Void doInBackground(Void... params) { |
| |
204 String newUrl = locationText.getText().toString().trim(); |
| |
205 String newKeyword = keywordText.getText().toString().trim(); |
| |
206 BrowserDB.updateBookmark(mContext.getContentResolver(), id, newUrl, nameText.getText().toString(), newKeyword); |
| |
207 return null; |
| |
208 } |
| |
209 |
| |
210 @Override |
| |
211 public void onPostExecute(Void result) { |
| |
212 Toast.makeText(mContext, R.string.bookmark_updated, Toast.LENGTH_SHORT).show(); |
| |
213 } |
| |
214 }).execute(); |
| |
215 } |
| |
216 }); |
| |
217 |
| |
218 editPrompt.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { |
| |
219 @Override |
| |
220 public void onClick(DialogInterface dialog, int whichButton) { |
| |
221 // do nothing |
| |
222 } |
| |
223 }); |
| |
224 |
| |
225 final AlertDialog dialog = editPrompt.create(); |
| |
226 |
| |
227 // Create our TextWatchers |
| |
228 LocationTextWatcher locationTextWatcher = new LocationTextWatcher(dialog); |
| |
229 KeywordTextWatcher keywordTextWatcher = new KeywordTextWatcher(dialog); |
| |
230 |
| |
231 // Cross reference the TextWatchers |
| |
232 locationTextWatcher.setPairedTextWatcher(keywordTextWatcher); |
| |
233 keywordTextWatcher.setPairedTextWatcher(locationTextWatcher); |
| |
234 |
| |
235 // Add the TextWatcher Listeners |
| |
236 locationText.addTextChangedListener(locationTextWatcher); |
| |
237 keywordText.addTextChangedListener(keywordTextWatcher); |
| |
238 |
| |
239 dialog.show(); |
| |
240 } |
| |
241 } |