mobile/android/base/home/TwoLinePageRow.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/home/TwoLinePageRow.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,238 @@
     1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +package org.mozilla.gecko.home;
    1.10 +
    1.11 +import java.lang.ref.WeakReference;
    1.12 +
    1.13 +import org.mozilla.gecko.R;
    1.14 +import org.mozilla.gecko.Tab;
    1.15 +import org.mozilla.gecko.Tabs;
    1.16 +import org.mozilla.gecko.db.BrowserContract.Combined;
    1.17 +import org.mozilla.gecko.db.BrowserDB.URLColumns;
    1.18 +import org.mozilla.gecko.favicons.Favicons;
    1.19 +import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
    1.20 +import org.mozilla.gecko.util.ThreadUtils;
    1.21 +import org.mozilla.gecko.widget.FaviconView;
    1.22 +
    1.23 +import android.content.Context;
    1.24 +import android.database.Cursor;
    1.25 +import android.graphics.Bitmap;
    1.26 +import android.text.TextUtils;
    1.27 +import android.util.AttributeSet;
    1.28 +import android.view.Gravity;
    1.29 +import android.view.LayoutInflater;
    1.30 +import android.widget.LinearLayout;
    1.31 +import android.widget.TextView;
    1.32 +
    1.33 +public class TwoLinePageRow extends LinearLayout
    1.34 +                            implements Tabs.OnTabsChangedListener {
    1.35 +
    1.36 +    protected static final int NO_ICON = 0;
    1.37 +
    1.38 +    private final TextView mTitle;
    1.39 +    private final TextView mUrl;
    1.40 +
    1.41 +    private int mSwitchToTabIconId;
    1.42 +    private int mPageTypeIconId;
    1.43 +
    1.44 +    private final FaviconView mFavicon;
    1.45 +
    1.46 +    private boolean mShowIcons;
    1.47 +    private int mLoadFaviconJobId = Favicons.NOT_LOADING;
    1.48 +
    1.49 +    // Only holds a reference to the FaviconView itself, so if the row gets
    1.50 +    // discarded while a task is outstanding, we'll leak less memory.
    1.51 +    private static class UpdateViewFaviconLoadedListener implements OnFaviconLoadedListener {
    1.52 +        private final WeakReference<FaviconView> view;
    1.53 +        public UpdateViewFaviconLoadedListener(FaviconView view) {
    1.54 +            this.view = new WeakReference<FaviconView>(view);
    1.55 +        }
    1.56 +
    1.57 +        @Override
    1.58 +        public void onFaviconLoaded(String url, String faviconURL, Bitmap favicon) {
    1.59 +            FaviconView v = view.get();
    1.60 +            if (v == null) {
    1.61 +                // Guess we stuck around after the TwoLinePageRow went away.
    1.62 +                return;
    1.63 +            }
    1.64 +
    1.65 +            if (favicon == null) {
    1.66 +                v.showDefaultFavicon();
    1.67 +                return;
    1.68 +            }
    1.69 +
    1.70 +            v.updateImage(favicon, faviconURL);
    1.71 +        }
    1.72 +    }
    1.73 +
    1.74 +    // Listener for handling Favicon loads.
    1.75 +    private final OnFaviconLoadedListener mFaviconListener;
    1.76 +
    1.77 +    // The URL for the page corresponding to this view.
    1.78 +    private String mPageUrl;
    1.79 +
    1.80 +    public TwoLinePageRow(Context context) {
    1.81 +        this(context, null);
    1.82 +    }
    1.83 +
    1.84 +    public TwoLinePageRow(Context context, AttributeSet attrs) {
    1.85 +        super(context, attrs);
    1.86 +
    1.87 +        setGravity(Gravity.CENTER_VERTICAL);
    1.88 +
    1.89 +        LayoutInflater.from(context).inflate(R.layout.two_line_page_row, this);
    1.90 +        mTitle = (TextView) findViewById(R.id.title);
    1.91 +        mUrl = (TextView) findViewById(R.id.url);
    1.92 +
    1.93 +        mSwitchToTabIconId = NO_ICON;
    1.94 +        mPageTypeIconId = NO_ICON;
    1.95 +        mShowIcons = true;
    1.96 +
    1.97 +        mFavicon = (FaviconView) findViewById(R.id.icon);
    1.98 +        mFaviconListener = new UpdateViewFaviconLoadedListener(mFavicon);
    1.99 +    }
   1.100 +
   1.101 +    @Override
   1.102 +    protected void onAttachedToWindow() {
   1.103 +        Tabs.registerOnTabsChangedListener(this);
   1.104 +    }
   1.105 +
   1.106 +    @Override
   1.107 +    protected void onDetachedFromWindow() {
   1.108 +        // Tabs' listener array is safe to modify during use: its
   1.109 +        // iteration pattern is based on snapshots.
   1.110 +        Tabs.unregisterOnTabsChangedListener(this);
   1.111 +    }
   1.112 +
   1.113 +    @Override
   1.114 +    public void onTabChanged(final Tab tab, final Tabs.TabEvents msg, final Object data) {
   1.115 +        switch(msg) {
   1.116 +            case ADDED:
   1.117 +            case CLOSED:
   1.118 +            case LOCATION_CHANGE:
   1.119 +                updateDisplayedUrl();
   1.120 +                break;
   1.121 +        }
   1.122 +    }
   1.123 +
   1.124 +    private void setTitle(String text) {
   1.125 +        mTitle.setText(text);
   1.126 +    }
   1.127 +
   1.128 +    protected void setUrl(String text) {
   1.129 +        mUrl.setText(text);
   1.130 +    }
   1.131 +
   1.132 +    protected void setUrl(int stringId) {
   1.133 +        mUrl.setText(stringId);
   1.134 +    }
   1.135 +
   1.136 +    protected String getUrl() {
   1.137 +        return mPageUrl;
   1.138 +    }
   1.139 +
   1.140 +    protected void setSwitchToTabIcon(int iconId) {
   1.141 +        if (mSwitchToTabIconId == iconId) {
   1.142 +            return;
   1.143 +        }
   1.144 +
   1.145 +        mSwitchToTabIconId = iconId;
   1.146 +        mUrl.setCompoundDrawablesWithIntrinsicBounds(mSwitchToTabIconId, 0, mPageTypeIconId, 0);
   1.147 +    }
   1.148 +
   1.149 +    private void setPageTypeIcon(int iconId) {
   1.150 +        if (mPageTypeIconId == iconId) {
   1.151 +            return;
   1.152 +        }
   1.153 +
   1.154 +        mPageTypeIconId = iconId;
   1.155 +        mUrl.setCompoundDrawablesWithIntrinsicBounds(mSwitchToTabIconId, 0, mPageTypeIconId, 0);
   1.156 +    }
   1.157 +
   1.158 +    /**
   1.159 +     * Stores the page URL, so that we can use it to replace "Switch to tab" if the open
   1.160 +     * tab changes or is closed.
   1.161 +     */
   1.162 +    private void updateDisplayedUrl(String url) {
   1.163 +        mPageUrl = url;
   1.164 +        updateDisplayedUrl();
   1.165 +    }
   1.166 +
   1.167 +    /**
   1.168 +     * Replaces the page URL with "Switch to tab" if there is already a tab open with that URL.
   1.169 +     * Only looks for tabs that are either private or non-private, depending on the current
   1.170 +     * selected tab.
   1.171 +     */
   1.172 +    protected void updateDisplayedUrl() {
   1.173 +        boolean isPrivate = Tabs.getInstance().getSelectedTab().isPrivate();
   1.174 +        Tab tab = Tabs.getInstance().getFirstTabForUrl(mPageUrl, isPrivate);
   1.175 +        if (!mShowIcons || tab == null) {
   1.176 +            setUrl(mPageUrl);
   1.177 +            setSwitchToTabIcon(NO_ICON);
   1.178 +        } else {
   1.179 +            setUrl(R.string.switch_to_tab);
   1.180 +            setSwitchToTabIcon(R.drawable.ic_url_bar_tab);
   1.181 +        }
   1.182 +    }
   1.183 +
   1.184 +    public void setShowIcons(boolean showIcons) {
   1.185 +        mShowIcons = showIcons;
   1.186 +    }
   1.187 +
   1.188 +    public void updateFromCursor(Cursor cursor) {
   1.189 +        if (cursor == null) {
   1.190 +            return;
   1.191 +        }
   1.192 +
   1.193 +        int titleIndex = cursor.getColumnIndexOrThrow(URLColumns.TITLE);
   1.194 +        final String title = cursor.getString(titleIndex);
   1.195 +
   1.196 +        int urlIndex = cursor.getColumnIndexOrThrow(URLColumns.URL);
   1.197 +        final String url = cursor.getString(urlIndex);
   1.198 +
   1.199 +        if (mShowIcons) {
   1.200 +            final int bookmarkIdIndex = cursor.getColumnIndex(Combined.BOOKMARK_ID);
   1.201 +            if (bookmarkIdIndex != -1) {
   1.202 +                final long bookmarkId = cursor.getLong(bookmarkIdIndex);
   1.203 +                final int displayIndex = cursor.getColumnIndex(Combined.DISPLAY);
   1.204 +
   1.205 +                final int display;
   1.206 +                if (displayIndex != -1) {
   1.207 +                    display = cursor.getInt(displayIndex);
   1.208 +                } else {
   1.209 +                    display = Combined.DISPLAY_NORMAL;
   1.210 +                }
   1.211 +
   1.212 +                // The bookmark id will be 0 (null in database) when the url
   1.213 +                // is not a bookmark.
   1.214 +                if (bookmarkId == 0) {
   1.215 +                    setPageTypeIcon(NO_ICON);
   1.216 +                } else if (display == Combined.DISPLAY_READER) {
   1.217 +                    setPageTypeIcon(R.drawable.ic_url_bar_reader);
   1.218 +                } else {
   1.219 +                    setPageTypeIcon(R.drawable.ic_url_bar_star);
   1.220 +                }
   1.221 +            } else {
   1.222 +                setPageTypeIcon(NO_ICON);
   1.223 +            }
   1.224 +        }
   1.225 +
   1.226 +        // Use the URL instead of an empty title for consistency with the normal URL
   1.227 +        // bar view - this is the equivalent of getDisplayTitle() in Tab.java
   1.228 +        setTitle(TextUtils.isEmpty(title) ? url : title);
   1.229 +
   1.230 +        // No point updating the below things if URL has not changed. Prevents evil Favicon flicker.
   1.231 +        if (url.equals(mPageUrl)) {
   1.232 +            return;
   1.233 +        }
   1.234 +
   1.235 +        // Blank the Favicon, so we don't show the wrong Favicon if we scroll and miss DB.
   1.236 +        mFavicon.clearImage();
   1.237 +        mLoadFaviconJobId = Favicons.getSizedFaviconForPageFromLocal(url, mFaviconListener);
   1.238 +
   1.239 +        updateDisplayedUrl(url);
   1.240 +    }
   1.241 +}

mercurial