// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.bookmarks;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListPopupWindow;
import android.widget.TextView;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
import org.chromium.chrome.browser.widget.TintedImageButton;
import org.chromium.chrome.browser.widget.selection.SelectableItemView;
import org.chromium.components.bookmarks.BookmarkId;
import java.util.List;
/**
* Common logic for bookmark and folder rows.
*/
abstract class BookmarkRow extends SelectableItemView<BookmarkId> implements BookmarkUIObserver {
protected ImageView mIconImageView;
protected TextView mTitleView;
protected TintedImageButton mMoreIcon;
protected BookmarkDelegate mDelegate;
protected BookmarkId mBookmarkId;
private ListPopupWindow mPopupMenu;
private boolean mIsAttachedToWindow = false;
/**
* Constructor for inflating from XML.
*/
public BookmarkRow(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Updates this row for the given {@link BookmarkId}.
* @return The {@link BookmarkItem} corresponding the given {@link BookmarkId}.
*/
BookmarkItem setBookmarkId(BookmarkId bookmarkId) {
mBookmarkId = bookmarkId;
BookmarkItem bookmarkItem = mDelegate.getModel().getBookmarkById(bookmarkId);
clearPopup();
if (isSelectable()) {
mMoreIcon.setVisibility(bookmarkItem.isEditable() ? VISIBLE : GONE);
setChecked(mDelegate.getSelectionDelegate().isItemSelected(bookmarkId));
}
super.setItem(bookmarkId);
return bookmarkItem;
}
private void initialize() {
mDelegate.addUIObserver(this);
updateSelectionState();
}
private void clearPopup() {
if (mPopupMenu != null) {
mPopupMenu.dismiss();
mPopupMenu = null;
}
}
private void cleanup() {
clearPopup();
if (mDelegate != null) mDelegate.removeUIObserver(this);
}
private void updateSelectionState() {
if (isSelectable()) mMoreIcon.setClickable(
!mDelegate.getSelectionDelegate().isSelectionEnabled());
}
/**
* @return Whether this row is selectable.
*/
protected boolean isSelectable() {
return true;
}
/**
* Show drop-down menu after user click on more-info icon
* @param view The anchor view for the menu
*/
private void showMenu(View view) {
if (mPopupMenu == null) {
mPopupMenu = new ListPopupWindow(getContext(), null, 0, R.style.BookmarkMenuStyle);
mPopupMenu.setAdapter(new ArrayAdapter<String>(
getContext(), R.layout.bookmark_popup_item, new String[] {
getContext().getString(R.string.bookmark_item_select),
getContext().getString(R.string.bookmark_item_edit),
getContext().getString(R.string.bookmark_item_move),
getContext().getString(R.string.bookmark_item_delete)}) {
private static final int MOVE_POSITION = 2;
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
// In some erroneous states, the popup window might hang around even if the
// activity is killed (crbug.com/594213), so null check here.
if (mDelegate == null || mDelegate.getModel() == null) return false;
if (position == MOVE_POSITION) {
BookmarkItem bookmark = mDelegate.getModel().getBookmarkById(mBookmarkId);
if (bookmark == null) return false;
return bookmark.isMovable();
}
return true;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.setEnabled(isEnabled(position));
return view;
}
});
mPopupMenu.setAnchorView(view);
mPopupMenu.setWidth(getResources().getDimensionPixelSize(
R.dimen.bookmark_item_popup_width));
mPopupMenu.setVerticalOffset(-view.getHeight());
mPopupMenu.setModal(true);
mPopupMenu.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
if (position == 0) {
setChecked(mDelegate.getSelectionDelegate().toggleSelectionForItem(
mBookmarkId));
} else if (position == 1) {
BookmarkItem item = mDelegate.getModel().getBookmarkById(mBookmarkId);
if (item.isFolder()) {
BookmarkAddEditFolderActivity.startEditFolderActivity(
getContext(), item.getId());
} else {
BookmarkUtils.startEditActivity(getContext(), item.getId());
}
} else if (position == 2) {
BookmarkFolderSelectActivity.startFolderSelectActivity(getContext(),
mBookmarkId);
} else if (position == 3) {
if (mDelegate != null && mDelegate.getModel() != null) {
mDelegate.getModel().deleteBookmarks(mBookmarkId);
}
}
// Somehow the on click event can be triggered way after we dismiss the popup.
// http://crbug.com/600642
if (mPopupMenu != null) mPopupMenu.dismiss();
}
});
}
mPopupMenu.show();
mPopupMenu.getListView().setDivider(null);
}
// FrameLayout implementations.
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mIconImageView = (ImageView) findViewById(R.id.bookmark_image);
mTitleView = (TextView) findViewById(R.id.title);
if (isSelectable()) {
mMoreIcon = (TintedImageButton) findViewById(R.id.more);
mMoreIcon.setVisibility(VISIBLE);
mMoreIcon.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
showMenu(view);
}
});
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mIsAttachedToWindow = true;
if (mDelegate != null) {
initialize();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mIsAttachedToWindow = false;
cleanup();
}
// SelectableItem overrides.
@Override
public boolean onLongClick(View view) {
if (!isSelectable()) return false;
return super.onLongClick(view);
}
@Override
public boolean isChecked() {
if (!isSelectable()) return false;
return super.isChecked();
}
@Override
public void toggle() {
setChecked(!isChecked());
}
@Override
public void setChecked(boolean checked) {
// Unselectable rows do not have highlight view.
if (isSelectable()) super.setChecked(checked);
}
@Override
public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {
if (isSelectable()) super.onSelectionStateChange(selectedBookmarks);
updateSelectionState();
}
// BookmarkUIObserver implementations.
@Override
public void onBookmarkDelegateInitialized(BookmarkDelegate delegate) {
super.setSelectionDelegate(delegate.getSelectionDelegate());
mDelegate = delegate;
if (mIsAttachedToWindow) initialize();
}
@Override
public void onDestroy() {
cleanup();
}
@Override
public void onFolderStateSet(BookmarkId folder) {
}
}