OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.enhancedbookmarks; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.content.Intent; |
| 9 import android.graphics.drawable.Drawable; |
| 10 import android.os.Bundle; |
| 11 import android.view.LayoutInflater; |
| 12 import android.view.View; |
| 13 import android.view.ViewGroup; |
| 14 import android.widget.AdapterView; |
| 15 import android.widget.BaseAdapter; |
| 16 import android.widget.ImageButton; |
| 17 import android.widget.ListView; |
| 18 import android.widget.TextView; |
| 19 |
| 20 import com.google.android.apps.chrome.R; |
| 21 |
| 22 import org.chromium.base.ApiCompatibilityUtils; |
| 23 import org.chromium.chrome.browser.BookmarksBridge.BookmarkItem; |
| 24 import org.chromium.chrome.browser.BookmarksBridge.BookmarkModelObserver; |
| 25 import org.chromium.chrome.browser.enhanced_bookmarks.EnhancedBookmarksModel; |
| 26 import org.chromium.chrome.browser.widget.TintedDrawable; |
| 27 import org.chromium.components.bookmarks.BookmarkId; |
| 28 |
| 29 import java.util.ArrayList; |
| 30 import java.util.List; |
| 31 |
| 32 /** |
| 33 * Dialog for moving bookmarks from one folder to another. A list of folders are
shown and the |
| 34 * hierarchy of bookmark model is presented by indentation of list items. This d
ialog can be shown |
| 35 * in two cases. One is when user choose to move an existing bookmark to a new f
older. The other is |
| 36 * when user creates a new folder/bookmark, he/she can choose which parent the n
ew folder/bookmark |
| 37 * belong to. |
| 38 * <p> |
| 39 * Note this fragment will not be restarted by OS. It will be dismissed if chrom
e is killed in |
| 40 * background. |
| 41 */ |
| 42 public class EnhancedBookmarkFolderSelectActivity extends EnhancedBookmarkActivi
tyBase implements |
| 43 AdapterView.OnItemClickListener { |
| 44 static final String |
| 45 INTENT_SELECTED_FOLDER = "EnhancedBookmarkFolderSelectActivity.selec
tedFolder"; |
| 46 static final String |
| 47 INTENT_IS_CREATING_FOLDER = "EnhancedBookmarkFolderSelectActivity.is
CreatingFolder"; |
| 48 static final String |
| 49 INTENT_BOOKMARKS_TO_MOVE = "EnhancedBookmarkFolderSelectActivity.boo
kmarksToMove"; |
| 50 static final int CREATE_FOLDER_REQUEST_CODE = 13; |
| 51 |
| 52 private EnhancedBookmarksModel mEnhancedBookmarksModel; |
| 53 private boolean mIsCreatingFolder; |
| 54 private List<BookmarkId> mBookmarksToMove; |
| 55 private BookmarkId mParentId; |
| 56 private FolderListAdapter mBookmarkIdsAdapter; |
| 57 private ListView mBookmarkIdsList; |
| 58 private ImageButton mBackButton; |
| 59 |
| 60 private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObse
rver() { |
| 61 @Override |
| 62 public void bookmarkModelChanged() { |
| 63 updateFolderList(); |
| 64 } |
| 65 |
| 66 @Override |
| 67 public void bookmarkNodeRemoved(BookmarkItem parent, int oldIndex, Bookm
arkItem node, |
| 68 boolean isDoingExtensiveChanges) { |
| 69 if (mBookmarksToMove.contains(node.getId())) { |
| 70 mBookmarksToMove.remove(node.getId()); |
| 71 if (mBookmarksToMove.isEmpty()) { |
| 72 finish(); |
| 73 return; |
| 74 } |
| 75 } else if (node.isFolder()) { |
| 76 updateFolderList(); |
| 77 } |
| 78 } |
| 79 }; |
| 80 |
| 81 /** |
| 82 * Starts a select folder activity. |
| 83 */ |
| 84 public static void startFolderSelectActivity(Context context, BookmarkId...
bookmarks) { |
| 85 assert bookmarks.length > 0; |
| 86 Intent intent = new Intent(context, EnhancedBookmarkFolderSelectActivity
.class); |
| 87 intent.putExtra(INTENT_IS_CREATING_FOLDER, false); |
| 88 ArrayList<String> bookmarkStrings = new ArrayList<>(bookmarks.length); |
| 89 for (BookmarkId id : bookmarks) { |
| 90 bookmarkStrings.add(id.toString()); |
| 91 } |
| 92 intent.putStringArrayListExtra(INTENT_BOOKMARKS_TO_MOVE, bookmarkStrings
); |
| 93 context.startActivity(intent); |
| 94 } |
| 95 |
| 96 /** |
| 97 * Starts a select folder activity for the new folder that is about to be cr
eated. This method |
| 98 * is only supposed to be called by {@link EnhancedBookmarkAddEditFolderActi
vity} |
| 99 */ |
| 100 public static void startNewFolderSelectActivity( |
| 101 EnhancedBookmarkAddEditFolderActivity activity, List<BookmarkId> boo
kmarks) { |
| 102 assert bookmarks.size() > 0; |
| 103 Intent intent = new Intent(activity, EnhancedBookmarkFolderSelectActivit
y.class); |
| 104 intent.putExtra(INTENT_IS_CREATING_FOLDER, true); |
| 105 ArrayList<String> bookmarkStrings = new ArrayList<>(bookmarks.size()); |
| 106 for (BookmarkId id : bookmarks) { |
| 107 bookmarkStrings.add(id.toString()); |
| 108 } |
| 109 intent.putStringArrayListExtra(INTENT_BOOKMARKS_TO_MOVE, bookmarkStrings
); |
| 110 activity.startActivityForResult(intent, |
| 111 EnhancedBookmarkAddEditFolderActivity.PARENT_FOLDER_REQUEST_CODE
); |
| 112 } |
| 113 |
| 114 @Override |
| 115 public void onCreate(Bundle savedInstanceState) { |
| 116 super.onCreate(savedInstanceState); |
| 117 EnhancedBookmarkUtils.setTaskDescriptionInDocumentMode(this, |
| 118 getString(R.string.enhanced_bookmark_choose_folder)); |
| 119 mEnhancedBookmarksModel = new EnhancedBookmarksModel(); |
| 120 mEnhancedBookmarksModel.addModelObserver(mBookmarkModelObserver); |
| 121 List<String> stringList = getIntent().getStringArrayListExtra(INTENT_BOO
KMARKS_TO_MOVE); |
| 122 mBookmarksToMove = new ArrayList<>(stringList.size()); |
| 123 for (String string : stringList) { |
| 124 mBookmarksToMove.add(BookmarkId.getBookmarkIdFromString(string)); |
| 125 } |
| 126 mIsCreatingFolder = getIntent().getBooleanExtra(INTENT_IS_CREATING_FOLDE
R, false); |
| 127 if (mIsCreatingFolder) { |
| 128 mParentId = mEnhancedBookmarksModel.getDefaultFolder(); |
| 129 } else { |
| 130 mParentId = mEnhancedBookmarksModel.getBookmarkById(mBookmarksToMove
.get(0)) |
| 131 .getParentId(); |
| 132 } |
| 133 |
| 134 setContentView(R.layout.eb_folder_select_activity); |
| 135 mBookmarkIdsList = (ListView) findViewById(R.id.eb_folder_list); |
| 136 mBookmarkIdsList.setOnItemClickListener(this); |
| 137 mBackButton = (ImageButton) findViewById(R.id.back); |
| 138 mBackButton.setOnClickListener(new View.OnClickListener() { |
| 139 @Override |
| 140 public void onClick(View v) { |
| 141 finish(); |
| 142 } |
| 143 }); |
| 144 updateFolderList(); |
| 145 } |
| 146 |
| 147 private void updateFolderList() { |
| 148 List<BookmarkId> folderList = new ArrayList<BookmarkId>(); |
| 149 List<Integer> depthList = new ArrayList<Integer>(); |
| 150 mEnhancedBookmarksModel.getMoveDestinations(folderList, depthList, mBook
marksToMove); |
| 151 List<FolderListEntry> entryList = new ArrayList<FolderListEntry>(folderL
ist.size() + 3); |
| 152 |
| 153 if (!mIsCreatingFolder) { |
| 154 entryList.add(new FolderListEntry(null, 0, |
| 155 getString(R.string.enhanced_bookmark_add_folder), false, |
| 156 FolderListEntry.TYPE_NEW_FOLDER)); |
| 157 entryList.add(new FolderListEntry(null, 0, "", false, FolderListEntr
y.TYPE_DIVIDER)); |
| 158 } |
| 159 |
| 160 for (int i = 0; i < folderList.size(); i++) { |
| 161 BookmarkId folder = folderList.get(i); |
| 162 if (mEnhancedBookmarksModel.getBookmarkCountForFolder(folder) == 0 |
| 163 && (folder.equals(mEnhancedBookmarksModel.getDesktopFolderId
()) |
| 164 || folder.equals(mEnhancedBookmarksModel.getOtherFolderId())
)) { |
| 165 continue; |
| 166 } |
| 167 String title = mEnhancedBookmarksModel.getBookmarkById(folder).getTi
tle(); |
| 168 entryList.add(new FolderListEntry(folder, depthList.get(i), title, |
| 169 folder.equals(mParentId), FolderListEntry.TYPE_NORMAL)); |
| 170 } |
| 171 mBookmarkIdsAdapter = new FolderListAdapter(entryList, this, |
| 172 mEnhancedBookmarksModel); |
| 173 mBookmarkIdsList.setAdapter(mBookmarkIdsAdapter); |
| 174 } |
| 175 |
| 176 @Override |
| 177 protected void onDestroy() { |
| 178 super.onDestroy(); |
| 179 mEnhancedBookmarksModel.removeModelObserver(mBookmarkModelObserver); |
| 180 mEnhancedBookmarksModel.destroy(); |
| 181 mEnhancedBookmarksModel = null; |
| 182 } |
| 183 |
| 184 /** |
| 185 * Moves bookmark from original parent to selected folder. In creation mode,
directly add the |
| 186 * new bookmark to selected folder instead of moving. |
| 187 */ |
| 188 @Override |
| 189 public void onItemClick(AdapterView<?> adapter, View view, int position, lon
g id) { |
| 190 FolderListEntry entry = (FolderListEntry) adapter.getItemAtPosition(posi
tion); |
| 191 if (mIsCreatingFolder) { |
| 192 BookmarkId selectedFolder = null; |
| 193 if (entry.mType == FolderListEntry.TYPE_NORMAL) { |
| 194 selectedFolder = entry.mId; |
| 195 } else { |
| 196 assert false : "Divider and new folder items should not " |
| 197 + "be clickable in creating mode"; |
| 198 } |
| 199 Intent intent = new Intent(); |
| 200 intent.putExtra(INTENT_SELECTED_FOLDER, selectedFolder.toString()); |
| 201 setResult(RESULT_OK, intent); |
| 202 finish(); |
| 203 } else if (entry.mType == FolderListEntry.TYPE_NEW_FOLDER) { |
| 204 EnhancedBookmarkAddEditFolderActivity.startAddFolderActivity(this, m
BookmarksToMove); |
| 205 } else if (entry.mType == FolderListEntry.TYPE_NORMAL) { |
| 206 mEnhancedBookmarksModel.moveBookmarks(mBookmarksToMove, entry.mId); |
| 207 finish(); |
| 208 } |
| 209 } |
| 210 |
| 211 @Override |
| 212 protected void onActivityResult(int requestCode, int resultCode, Intent data
) { |
| 213 super.onActivityResult(requestCode, resultCode, data); |
| 214 assert !mIsCreatingFolder; |
| 215 if (requestCode == CREATE_FOLDER_REQUEST_CODE && resultCode == RESULT_OK
) { |
| 216 BookmarkId createdBookmark = BookmarkId.getBookmarkIdFromString(data
.getStringExtra( |
| 217 EnhancedBookmarkAddEditFolderActivity.INTENT_CREATED_BOOKMAR
K)); |
| 218 mEnhancedBookmarksModel.moveBookmarks(mBookmarksToMove, createdBookm
ark); |
| 219 finish(); |
| 220 } |
| 221 } |
| 222 |
| 223 /** |
| 224 * Data object representing a folder entry used in FolderListAdapter. |
| 225 */ |
| 226 private static class FolderListEntry { |
| 227 public static final int TYPE_NEW_FOLDER = 0; |
| 228 public static final int TYPE_DIVIDER = 1; |
| 229 public static final int TYPE_NORMAL = 2; |
| 230 |
| 231 BookmarkId mId; |
| 232 String mTitle; |
| 233 int mDepth; |
| 234 boolean mIsSelected; |
| 235 int mType; |
| 236 |
| 237 public FolderListEntry(BookmarkId bookmarkId, int depth, String title, b
oolean isSelected, |
| 238 int type) { |
| 239 assert type == TYPE_DIVIDER || type == TYPE_NEW_FOLDER || type == TY
PE_NORMAL; |
| 240 mDepth = depth; |
| 241 mId = bookmarkId; |
| 242 mTitle = title; |
| 243 mIsSelected = isSelected; |
| 244 mType = type; |
| 245 } |
| 246 } |
| 247 |
| 248 private static class FolderListAdapter extends BaseAdapter { |
| 249 // The maximum depth that will be indented. Folders with a depth greater |
| 250 // than this will all appear at this same depth. |
| 251 private static final int MAX_FOLDER_DEPTH = 5; |
| 252 |
| 253 private final int mBasePadding; |
| 254 private final int mPaddingIncrement; |
| 255 |
| 256 private BookmarkId mDesktopNodeId = null; |
| 257 private BookmarkId mMobileNodeId = null; |
| 258 private BookmarkId mOthersNodeId = null; |
| 259 |
| 260 List<FolderListEntry> mEntryList; |
| 261 Context mContext; |
| 262 |
| 263 public FolderListAdapter(List<FolderListEntry> entryList, Context contex
t, |
| 264 EnhancedBookmarksModel model) { |
| 265 mContext = context; |
| 266 mEntryList = entryList; |
| 267 mBasePadding = mContext.getResources() |
| 268 .getDimensionPixelSize(R.dimen.enhanced_bookmark_folder_item
_left); |
| 269 mPaddingIncrement = mBasePadding * 2; |
| 270 |
| 271 mMobileNodeId = model.getMobileFolderId(); |
| 272 mDesktopNodeId = model.getDesktopFolderId(); |
| 273 mOthersNodeId = model.getOtherFolderId(); |
| 274 } |
| 275 |
| 276 @Override |
| 277 public int getCount() { |
| 278 return mEntryList.size(); |
| 279 } |
| 280 |
| 281 @Override |
| 282 public FolderListEntry getItem(int position) { |
| 283 return mEntryList.get(position); |
| 284 } |
| 285 |
| 286 @Override |
| 287 public long getItemId(int position) { |
| 288 return position; |
| 289 } |
| 290 |
| 291 /** |
| 292 * There are 3 types of entries: new folder, divider and normal. |
| 293 */ |
| 294 @Override |
| 295 public int getViewTypeCount() { |
| 296 return 3; |
| 297 } |
| 298 |
| 299 @Override |
| 300 public int getItemViewType(int position) { |
| 301 FolderListEntry entry = getItem(position); |
| 302 return entry.mType; |
| 303 } |
| 304 |
| 305 @Override |
| 306 public View getView(int position, View convertView, ViewGroup parent) { |
| 307 final FolderListEntry entry = getItem(position); |
| 308 if (convertView != null && entry.mType != FolderListEntry.TYPE_NORMA
L) { |
| 309 return convertView; |
| 310 } |
| 311 if (convertView == null) { |
| 312 if (entry.mType == FolderListEntry.TYPE_DIVIDER) { |
| 313 return LayoutInflater.from(parent.getContext()).inflate( |
| 314 R.layout.eb_list_divider, parent, false); |
| 315 } else { |
| 316 convertView = LayoutInflater.from(parent.getContext()).infla
te( |
| 317 R.layout.eb_folder_select_item, parent, false); |
| 318 } |
| 319 } |
| 320 TextView textView = (TextView) convertView; |
| 321 textView.setText(entry.mTitle); |
| 322 |
| 323 setUpIcons(entry, textView); |
| 324 setUpPadding(entry, textView); |
| 325 |
| 326 return textView; |
| 327 } |
| 328 |
| 329 /** |
| 330 * Sets compound drawables (icons) for different kinds of list entries, |
| 331 * i.e. New Folder, Normal and Selected. |
| 332 */ |
| 333 private void setUpIcons(FolderListEntry entry, TextView textView) { |
| 334 // Divider entry should not have start drawables. |
| 335 int iconId = 0; |
| 336 |
| 337 if (entry.mType == FolderListEntry.TYPE_NORMAL) { |
| 338 // TODO(kkimlabs): This special icon logic is similar to |
| 339 // EnhancedBookmarkDrawerListViewAdapter. Ideall
y we should |
| 340 // share the logic. |
| 341 // Only top folders have special icons. |
| 342 if (entry.mDepth == 0) { |
| 343 |
| 344 if (entry.mId.equals(mMobileNodeId)) { |
| 345 iconId = R.drawable.eb_mobile; |
| 346 } else if (entry.mId.equals(mDesktopNodeId)) { |
| 347 iconId = R.drawable.eb_bookmarks_bar; |
| 348 } else if (entry.mId.equals(mOthersNodeId)) { |
| 349 iconId = R.drawable.eb_others; |
| 350 } |
| 351 } else { |
| 352 iconId = R.drawable.eb_folder; |
| 353 } |
| 354 } else if (entry.mType == FolderListEntry.TYPE_NEW_FOLDER) { |
| 355 // For new folder, start_icon is different. |
| 356 iconId = R.drawable.eb_add_folder; |
| 357 } |
| 358 |
| 359 Drawable drawableStart = TintedDrawable.constructTintedDrawable(text
View.getResources(), |
| 360 iconId); |
| 361 // Selected entry has an end_icon, a blue check mark. |
| 362 Drawable drawableEnd = entry.mIsSelected ? ApiCompatibilityUtils.get
Drawable( |
| 363 textView.getResources(), R.drawable.eb_check_blue) : null; |
| 364 ApiCompatibilityUtils.setCompoundDrawablesRelativeWithIntrinsicBound
s(textView, |
| 365 drawableStart, null, drawableEnd, null); |
| 366 } |
| 367 |
| 368 /** |
| 369 * Sets up padding for the entry |
| 370 */ |
| 371 private void setUpPadding(FolderListEntry entry, TextView textView) { |
| 372 int paddingStart = mBasePadding + Math.min(entry.mDepth, MAX_FOLDER_
DEPTH) |
| 373 * mPaddingIncrement; |
| 374 ApiCompatibilityUtils.setPaddingRelative(textView, paddingStart, 0, |
| 375 mBasePadding, 0); |
| 376 } |
| 377 |
| 378 @Override |
| 379 public boolean areAllItemsEnabled() { |
| 380 return false; |
| 381 } |
| 382 |
| 383 /** |
| 384 * Disables divider as an entry in list |
| 385 */ |
| 386 @Override |
| 387 public boolean isEnabled(int position) { |
| 388 return getItem(position).mType != FolderListEntry.TYPE_DIVIDER; |
| 389 } |
| 390 } |
| 391 } |
OLD | NEW |