2013-05-30 17:53:13 -07:00
|
|
|
/* -*- 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.home;
|
|
|
|
|
2014-02-22 19:53:01 -08:00
|
|
|
import java.lang.ref.WeakReference;
|
|
|
|
|
2013-05-30 17:53:13 -07:00
|
|
|
import org.mozilla.gecko.R;
|
2013-08-06 16:19:42 -07:00
|
|
|
import org.mozilla.gecko.Tab;
|
2013-06-10 17:17:13 -07:00
|
|
|
import org.mozilla.gecko.Tabs;
|
2013-06-14 09:26:36 -07:00
|
|
|
import org.mozilla.gecko.db.BrowserContract.Combined;
|
2013-05-30 17:53:13 -07:00
|
|
|
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
2014-02-22 19:53:01 -08:00
|
|
|
import org.mozilla.gecko.favicons.Favicons;
|
2013-10-11 16:42:39 -07:00
|
|
|
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
|
2013-08-06 16:19:42 -07:00
|
|
|
import org.mozilla.gecko.util.ThreadUtils;
|
2013-05-30 17:53:13 -07:00
|
|
|
import org.mozilla.gecko.widget.FaviconView;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.database.Cursor;
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.util.AttributeSet;
|
2014-02-20 02:54:18 -08:00
|
|
|
import android.view.Gravity;
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.widget.LinearLayout;
|
2014-02-07 05:29:40 -08:00
|
|
|
import android.widget.TextView;
|
2013-05-30 17:53:13 -07:00
|
|
|
|
2014-02-20 02:54:18 -08:00
|
|
|
public class TwoLinePageRow extends LinearLayout
|
2013-08-06 16:19:42 -07:00
|
|
|
implements Tabs.OnTabsChangedListener {
|
2013-05-30 17:53:13 -07:00
|
|
|
|
2014-02-07 05:29:40 -08:00
|
|
|
private static final int NO_ICON = 0;
|
|
|
|
|
2014-02-20 02:54:18 -08:00
|
|
|
private final TextView mTitle;
|
|
|
|
private final TextView mUrl;
|
|
|
|
|
2014-02-07 05:29:40 -08:00
|
|
|
private int mSwitchToTabIconId;
|
|
|
|
private int mPageTypeIconId;
|
|
|
|
|
2013-05-30 17:53:13 -07:00
|
|
|
private final FaviconView mFavicon;
|
|
|
|
|
2013-07-22 12:49:39 -07:00
|
|
|
private boolean mShowIcons;
|
2013-10-11 16:42:39 -07:00
|
|
|
private int mLoadFaviconJobId = Favicons.NOT_LOADING;
|
|
|
|
|
2013-11-04 11:48:58 -08:00
|
|
|
// Only holds a reference to the FaviconView itself, so if the row gets
|
|
|
|
// discarded while a task is outstanding, we'll leak less memory.
|
|
|
|
private static class UpdateViewFaviconLoadedListener implements OnFaviconLoadedListener {
|
|
|
|
private final WeakReference<FaviconView> view;
|
|
|
|
public UpdateViewFaviconLoadedListener(FaviconView view) {
|
|
|
|
this.view = new WeakReference<FaviconView>(view);
|
|
|
|
}
|
|
|
|
|
2013-10-11 16:42:39 -07:00
|
|
|
@Override
|
|
|
|
public void onFaviconLoaded(String url, String faviconURL, Bitmap favicon) {
|
2013-11-04 11:48:58 -08:00
|
|
|
FaviconView v = view.get();
|
|
|
|
if (v == null) {
|
|
|
|
// Guess we stuck around after the TwoLinePageRow went away.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (favicon == null) {
|
|
|
|
v.showDefaultFavicon();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-11-05 17:57:04 -08:00
|
|
|
v.updateImage(favicon, faviconURL);
|
2013-10-11 16:42:39 -07:00
|
|
|
}
|
2013-11-04 11:48:58 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Listener for handling Favicon loads.
|
|
|
|
private final OnFaviconLoadedListener mFaviconListener;
|
2013-06-14 09:26:36 -07:00
|
|
|
|
2013-08-06 16:19:42 -07:00
|
|
|
// The URL for the page corresponding to this view.
|
|
|
|
private String mPageUrl;
|
|
|
|
|
2013-05-30 17:53:13 -07:00
|
|
|
public TwoLinePageRow(Context context) {
|
|
|
|
this(context, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public TwoLinePageRow(Context context, AttributeSet attrs) {
|
2013-06-04 14:18:02 -07:00
|
|
|
super(context, attrs);
|
2013-05-30 17:53:13 -07:00
|
|
|
|
2014-02-20 02:54:18 -08:00
|
|
|
setGravity(Gravity.CENTER_VERTICAL);
|
|
|
|
|
|
|
|
LayoutInflater.from(context).inflate(R.layout.two_line_page_row, this);
|
|
|
|
mTitle = (TextView) findViewById(R.id.title);
|
|
|
|
mUrl = (TextView) findViewById(R.id.url);
|
2013-06-14 09:26:36 -07:00
|
|
|
|
2014-02-07 05:29:40 -08:00
|
|
|
mSwitchToTabIconId = NO_ICON;
|
|
|
|
mPageTypeIconId = NO_ICON;
|
2014-02-20 02:54:18 -08:00
|
|
|
mShowIcons = true;
|
2014-02-07 05:29:40 -08:00
|
|
|
|
2014-01-27 13:29:54 -08:00
|
|
|
mFavicon = (FaviconView) findViewById(R.id.icon);
|
2013-11-04 11:48:58 -08:00
|
|
|
mFaviconListener = new UpdateViewFaviconLoadedListener(mFavicon);
|
2013-05-30 17:53:13 -07:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:19:42 -07:00
|
|
|
@Override
|
|
|
|
protected void onAttachedToWindow() {
|
|
|
|
Tabs.registerOnTabsChangedListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onDetachedFromWindow() {
|
|
|
|
// Delay removing the listener to avoid modifying mTabsChangedListeners
|
|
|
|
// while notifyListeners is iterating through the array.
|
|
|
|
ThreadUtils.postToUiThread(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
Tabs.unregisterOnTabsChangedListener(TwoLinePageRow.this);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onTabChanged(final Tab tab, final Tabs.TabEvents msg, final Object data) {
|
|
|
|
switch(msg) {
|
|
|
|
case ADDED:
|
|
|
|
case CLOSED:
|
|
|
|
case LOCATION_CHANGE:
|
|
|
|
updateDisplayedUrl();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-20 02:54:18 -08:00
|
|
|
private void setTitle(String text) {
|
|
|
|
mTitle.setText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setUrl(String text) {
|
|
|
|
mUrl.setText(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void setUrl(int stringId) {
|
|
|
|
mUrl.setText(stringId);
|
|
|
|
}
|
|
|
|
|
2014-02-07 05:29:40 -08:00
|
|
|
private void setSwitchToTabIcon(int iconId) {
|
|
|
|
if (mSwitchToTabIconId == iconId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mSwitchToTabIconId = iconId;
|
2014-02-20 02:54:18 -08:00
|
|
|
mUrl.setCompoundDrawablesWithIntrinsicBounds(mSwitchToTabIconId, 0, mPageTypeIconId, 0);
|
2014-02-07 05:29:40 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void setPageTypeIcon(int iconId) {
|
|
|
|
if (mPageTypeIconId == iconId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mPageTypeIconId = iconId;
|
2014-02-20 02:54:18 -08:00
|
|
|
mUrl.setCompoundDrawablesWithIntrinsicBounds(mSwitchToTabIconId, 0, mPageTypeIconId, 0);
|
2014-02-07 05:29:40 -08:00
|
|
|
}
|
|
|
|
|
2013-08-06 16:19:42 -07:00
|
|
|
/**
|
|
|
|
* Stores the page URL, so that we can use it to replace "Switch to tab" if the open
|
|
|
|
* tab changes or is closed.
|
|
|
|
*/
|
|
|
|
private void updateDisplayedUrl(String url) {
|
|
|
|
mPageUrl = url;
|
|
|
|
updateDisplayedUrl();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Replaces the page URL with "Switch to tab" if there is already a tab open with that URL.
|
2013-10-03 17:13:42 -07:00
|
|
|
* Only looks for tabs that are either private or non-private, depending on the current
|
|
|
|
* selected tab.
|
2013-08-06 16:19:42 -07:00
|
|
|
*/
|
|
|
|
private void updateDisplayedUrl() {
|
2013-10-03 17:13:42 -07:00
|
|
|
boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
|
2014-01-28 11:56:26 -08:00
|
|
|
Tab tab = Tabs.getInstance().getFirstTabForUrl(mPageUrl, isPrivate);
|
|
|
|
if (!mShowIcons || tab == null) {
|
2014-02-20 02:54:18 -08:00
|
|
|
setUrl(mPageUrl);
|
2014-02-07 05:29:40 -08:00
|
|
|
setSwitchToTabIcon(NO_ICON);
|
2013-08-06 16:19:42 -07:00
|
|
|
} else {
|
2014-02-20 02:54:18 -08:00
|
|
|
setUrl(R.string.switch_to_tab);
|
2014-02-07 05:29:40 -08:00
|
|
|
setSwitchToTabIcon(R.drawable.ic_url_bar_tab);
|
2013-08-06 16:19:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-22 12:49:39 -07:00
|
|
|
public void setShowIcons(boolean showIcons) {
|
|
|
|
mShowIcons = showIcons;
|
|
|
|
}
|
|
|
|
|
2013-05-30 17:53:13 -07:00
|
|
|
public void updateFromCursor(Cursor cursor) {
|
|
|
|
if (cursor == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE);
|
|
|
|
final String title = cursor.getString(titleIndex);
|
|
|
|
|
|
|
|
int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
|
|
|
|
final String url = cursor.getString(urlIndex);
|
|
|
|
|
2013-10-11 16:42:39 -07:00
|
|
|
if (mShowIcons) {
|
|
|
|
final int bookmarkIdIndex = cursor.getColumnIndex(Combined.BOOKMARK_ID);
|
|
|
|
if (bookmarkIdIndex != -1) {
|
|
|
|
final long bookmarkId = cursor.getLong(bookmarkIdIndex);
|
|
|
|
final int displayIndex = cursor.getColumnIndex(Combined.DISPLAY);
|
|
|
|
|
|
|
|
final int display;
|
|
|
|
if (displayIndex != -1) {
|
|
|
|
display = cursor.getInt(displayIndex);
|
|
|
|
} else {
|
|
|
|
display = Combined.DISPLAY_NORMAL;
|
|
|
|
}
|
2013-06-14 09:26:36 -07:00
|
|
|
|
2013-10-11 16:42:39 -07:00
|
|
|
// The bookmark id will be 0 (null in database) when the url
|
|
|
|
// is not a bookmark.
|
|
|
|
if (bookmarkId == 0) {
|
2014-02-07 05:29:40 -08:00
|
|
|
setPageTypeIcon(NO_ICON);
|
2013-10-11 16:42:39 -07:00
|
|
|
} else if (display == Combined.DISPLAY_READER) {
|
2014-02-07 05:29:40 -08:00
|
|
|
setPageTypeIcon(R.drawable.ic_url_bar_reader);
|
2013-10-11 16:42:39 -07:00
|
|
|
} else {
|
2014-02-07 05:29:40 -08:00
|
|
|
setPageTypeIcon(R.drawable.ic_url_bar_star);
|
2013-10-11 16:42:39 -07:00
|
|
|
}
|
2013-06-14 09:26:36 -07:00
|
|
|
} else {
|
2014-02-07 05:29:40 -08:00
|
|
|
setPageTypeIcon(NO_ICON);
|
2013-06-14 09:26:36 -07:00
|
|
|
}
|
|
|
|
}
|
2013-09-18 09:58:25 -07:00
|
|
|
|
2013-12-03 12:39:27 -08:00
|
|
|
// Use the URL instead of an empty title for consistency with the normal URL
|
|
|
|
// bar view - this is the equivalent of getDisplayTitle() in Tab.java
|
2014-02-07 05:29:40 -08:00
|
|
|
setTitle(TextUtils.isEmpty(title) ? url : title);
|
2013-12-03 12:39:27 -08:00
|
|
|
|
2013-10-11 16:42:39 -07:00
|
|
|
// No point updating the below things if URL has not changed. Prevents evil Favicon flicker.
|
|
|
|
if (url.equals(mPageUrl)) {
|
|
|
|
return;
|
2013-09-18 09:58:25 -07:00
|
|
|
}
|
|
|
|
|
2013-10-11 16:42:39 -07:00
|
|
|
// Blank the Favicon, so we don't show the wrong Favicon if we scroll and miss DB.
|
|
|
|
mFavicon.clearImage();
|
|
|
|
mLoadFaviconJobId = Favicons.getSizedFaviconForPageFromLocal(url, mFaviconListener);
|
2013-09-18 09:58:25 -07:00
|
|
|
|
2013-10-11 16:42:39 -07:00
|
|
|
updateDisplayedUrl(url);
|
2013-09-18 09:58:25 -07:00
|
|
|
}
|
2013-05-30 17:53:13 -07:00
|
|
|
}
|