mobile/android/base/home/PinSiteDialog.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/base/home/PinSiteDialog.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 org.mozilla.gecko.R;
    1.12 +import org.mozilla.gecko.db.BrowserDB.URLColumns;
    1.13 +
    1.14 +import android.content.Context;
    1.15 +import android.database.Cursor;
    1.16 +import android.os.Bundle;
    1.17 +import android.support.v4.app.DialogFragment;
    1.18 +import android.support.v4.app.LoaderManager;
    1.19 +import android.support.v4.app.LoaderManager.LoaderCallbacks;
    1.20 +import android.support.v4.content.Loader;
    1.21 +import android.support.v4.widget.CursorAdapter;
    1.22 +import android.text.Editable;
    1.23 +import android.text.TextUtils;
    1.24 +import android.text.TextWatcher;
    1.25 +import android.view.KeyEvent;
    1.26 +import android.view.LayoutInflater;
    1.27 +import android.view.View;
    1.28 +import android.view.ViewGroup;
    1.29 +import android.view.WindowManager;
    1.30 +import android.widget.AdapterView;
    1.31 +import android.widget.EditText;
    1.32 +import android.widget.ListView;
    1.33 +
    1.34 +/**
    1.35 + * Dialog fragment that displays frecency search results, for pinning a site, in a GridView.
    1.36 + */
    1.37 +class PinSiteDialog extends DialogFragment {
    1.38 +    // Listener for url selection
    1.39 +    public static interface OnSiteSelectedListener {
    1.40 +        public void onSiteSelected(String url, String title);
    1.41 +    }
    1.42 +
    1.43 +    // Cursor loader ID for search query
    1.44 +    private static final int LOADER_ID_SEARCH = 0;
    1.45 +
    1.46 +    // Holds the current search term to use in the query
    1.47 +    private String mSearchTerm;
    1.48 +
    1.49 +    // Adapter for the list of search results
    1.50 +    private SearchAdapter mAdapter;
    1.51 +
    1.52 +    // Search entry
    1.53 +    private EditText mSearch;
    1.54 +
    1.55 +    // Search results
    1.56 +    private ListView mList;
    1.57 +
    1.58 +    // Callbacks used for the search loader
    1.59 +    private CursorLoaderCallbacks mLoaderCallbacks;
    1.60 +
    1.61 +    // Bookmark selected listener
    1.62 +    private OnSiteSelectedListener mOnSiteSelectedListener;
    1.63 +
    1.64 +    public static PinSiteDialog newInstance() {
    1.65 +        return new PinSiteDialog();
    1.66 +    }
    1.67 +
    1.68 +    private PinSiteDialog() {
    1.69 +    }
    1.70 +
    1.71 +    @Override
    1.72 +    public void onCreate(Bundle savedInstanceState) {
    1.73 +        super.onCreate(savedInstanceState);
    1.74 +
    1.75 +        setStyle(DialogFragment.STYLE_NO_TITLE, android.R.style.Theme_Holo_Light_Dialog);
    1.76 +    }
    1.77 +
    1.78 +    @Override
    1.79 +    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    1.80 +        // All list views are styled to look the same with a global activity theme.
    1.81 +        // If the style of the list changes, inflate it from an XML.
    1.82 +        return inflater.inflate(R.layout.pin_site_dialog, container, false);
    1.83 +    }
    1.84 +
    1.85 +    @Override
    1.86 +    public void onViewCreated(View view, Bundle savedInstanceState) {
    1.87 +        super.onViewCreated(view, savedInstanceState);
    1.88 +
    1.89 +        mSearch = (EditText) view.findViewById(R.id.search);
    1.90 +        mSearch.addTextChangedListener(new TextWatcher() {
    1.91 +            @Override
    1.92 +            public void afterTextChanged(Editable s) {
    1.93 +            }
    1.94 +
    1.95 +            @Override
    1.96 +            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    1.97 +            }
    1.98 +
    1.99 +            @Override
   1.100 +            public void onTextChanged(CharSequence s, int start, int before, int count) {
   1.101 +                setSearchTerm(mSearch.getText().toString());
   1.102 +                filter(mSearchTerm);
   1.103 +            }
   1.104 +        });
   1.105 +
   1.106 +        mSearch.setOnKeyListener(new View.OnKeyListener() {
   1.107 +            @Override
   1.108 +            public boolean onKey(View v, int keyCode, KeyEvent event) {
   1.109 +                if (keyCode != KeyEvent.KEYCODE_ENTER || mOnSiteSelectedListener == null) {
   1.110 +                    return false;
   1.111 +                }
   1.112 +
   1.113 +                // If the user manually entered a search term or URL, wrap the value in
   1.114 +                // a special URI until we can get a valid URL for this bookmark.
   1.115 +                final String text = mSearch.getText().toString().trim();
   1.116 +                if (!TextUtils.isEmpty(text)) {
   1.117 +                    final String url = TopSitesPanel.encodeUserEnteredUrl(text);
   1.118 +                    mOnSiteSelectedListener.onSiteSelected(url, text);
   1.119 +                    dismiss();
   1.120 +                }
   1.121 +
   1.122 +                return true;
   1.123 +            }
   1.124 +        });
   1.125 +
   1.126 +        mSearch.setOnFocusChangeListener(new View.OnFocusChangeListener() {
   1.127 +            @Override
   1.128 +            public void onFocusChange(View v, boolean hasFocus) {
   1.129 +                if (hasFocus) {
   1.130 +                    getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
   1.131 +                }
   1.132 +            }
   1.133 +        });
   1.134 +
   1.135 +        mList = (HomeListView) view.findViewById(R.id.list);
   1.136 +        mList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
   1.137 +            @Override
   1.138 +            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
   1.139 +                if (mOnSiteSelectedListener != null) {
   1.140 +                    final Cursor c = mAdapter.getCursor();
   1.141 +                    if (c == null || !c.moveToPosition(position)) {
   1.142 +                        return;
   1.143 +                    }
   1.144 +
   1.145 +                    final String url = c.getString(c.getColumnIndexOrThrow(URLColumns.URL));
   1.146 +                    final String title = c.getString(c.getColumnIndexOrThrow(URLColumns.TITLE));
   1.147 +                    mOnSiteSelectedListener.onSiteSelected(url, title);
   1.148 +                }
   1.149 +
   1.150 +                // Dismiss the fragment and the dialog.
   1.151 +                dismiss();
   1.152 +            }
   1.153 +        });
   1.154 +    }
   1.155 +
   1.156 +    @Override
   1.157 +    public void onActivityCreated(Bundle savedInstanceState) {
   1.158 +        super.onActivityCreated(savedInstanceState);
   1.159 +
   1.160 +        final LoaderManager manager = getLoaderManager();
   1.161 +
   1.162 +        // Initialize the search adapter
   1.163 +        mAdapter = new SearchAdapter(getActivity());
   1.164 +        mList.setAdapter(mAdapter);
   1.165 +
   1.166 +        // Create callbacks before the initial loader is started
   1.167 +        mLoaderCallbacks = new CursorLoaderCallbacks();
   1.168 +
   1.169 +        // Reconnect to the loader only if present
   1.170 +        manager.initLoader(LOADER_ID_SEARCH, null, mLoaderCallbacks);
   1.171 +
   1.172 +        // If there is a search term, put it in the text field
   1.173 +        if (!TextUtils.isEmpty(mSearchTerm)) {
   1.174 +            mSearch.setText(mSearchTerm);
   1.175 +            mSearch.selectAll();
   1.176 +        }
   1.177 +
   1.178 +        // Always start with an empty filter
   1.179 +        filter("");
   1.180 +    }
   1.181 +
   1.182 +    @Override
   1.183 +    public void onDestroyView() {
   1.184 +        super.onDestroyView();
   1.185 +
   1.186 +        // Discard any additional site selection as the dialog
   1.187 +        // is getting destroyed (see bug 935542).
   1.188 +        setOnSiteSelectedListener(null);
   1.189 +    }
   1.190 +
   1.191 +    public void setSearchTerm(String searchTerm) {
   1.192 +        mSearchTerm = searchTerm;
   1.193 +    }
   1.194 +
   1.195 +    private void filter(String searchTerm) {
   1.196 +        // Restart loaders with the new search term
   1.197 +        SearchLoader.restart(getLoaderManager(), LOADER_ID_SEARCH, mLoaderCallbacks, searchTerm);
   1.198 +    }
   1.199 +
   1.200 +    public void setOnSiteSelectedListener(OnSiteSelectedListener listener) {
   1.201 +        mOnSiteSelectedListener = listener;
   1.202 +    }
   1.203 +
   1.204 +    private static class SearchAdapter extends CursorAdapter {
   1.205 +        private LayoutInflater mInflater;
   1.206 +
   1.207 +        public SearchAdapter(Context context) {
   1.208 +            super(context, null, 0);
   1.209 +            mInflater = LayoutInflater.from(context);
   1.210 +        }
   1.211 +
   1.212 +        @Override
   1.213 +        public void bindView(View view, Context context, Cursor cursor) {
   1.214 +            TwoLinePageRow row = (TwoLinePageRow) view;
   1.215 +            row.setShowIcons(false);
   1.216 +            row.updateFromCursor(cursor);
   1.217 +        }
   1.218 +
   1.219 +        @Override
   1.220 +        public View newView(Context context, Cursor cursor, ViewGroup parent) {
   1.221 +            return (TwoLinePageRow) mInflater.inflate(R.layout.home_item_row, parent, false);
   1.222 +        }
   1.223 +    }
   1.224 +
   1.225 +    private class CursorLoaderCallbacks implements LoaderCallbacks<Cursor> {
   1.226 +        @Override
   1.227 +        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
   1.228 +            return SearchLoader.createInstance(getActivity(), args);
   1.229 +        }
   1.230 +
   1.231 +        @Override
   1.232 +        public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
   1.233 +            mAdapter.swapCursor(c);
   1.234 +        }
   1.235 +
   1.236 +        @Override
   1.237 +        public void onLoaderReset(Loader<Cursor> loader) {
   1.238 +            mAdapter.swapCursor(null);
   1.239 +        }
   1.240 +    }
   1.241 +}

mercurial