mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
265 lines
8.8 KiB
Java
265 lines
8.8 KiB
Java
/* -*- 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;
|
|||
|
|||
import android.content.ContentResolver;
|
|||
import android.content.Context;
|
|||
import android.content.res.Resources;
|
|||
Bug 671131 - (Part 2) Make observer to update history tab when history item is removed. r=bnicholson
|
import android.database.ContentObserver;
|
||
import android.database.Cursor;
|
|||
import android.graphics.Bitmap;
|
|||
import android.graphics.BitmapFactory;
|
|||
import android.graphics.Color;
|
|||
import android.graphics.LightingColorFilter;
|
|||
import android.graphics.drawable.Drawable;
|
|||
import android.os.AsyncTask;
|
|||
import android.os.SystemClock;
|
|||
|
import android.text.TextUtils;
|
||
import android.util.AttributeSet;
|
|||
import android.util.Log;
|
|||
import android.util.Pair;
|
|||
import android.view.LayoutInflater;
|
|||
import android.view.MotionEvent;
|
|||
import android.view.View;
|
|||
import android.view.ViewGroup;
|
|||
import android.view.inputmethod.InputMethodManager;
|
|||
import android.widget.AdapterView;
|
|||
import android.widget.ExpandableListView;
|
|||
import android.widget.ImageView;
|
|||
|
import android.widget.LinearLayout;
|
||
import android.widget.ListView;
|
|||
import android.widget.SimpleCursorAdapter;
|
|||
import android.widget.SimpleExpandableListAdapter;
|
|||
import android.widget.TabHost;
|
|||
import android.widget.TextView;
|
|||
|
|||
|
import java.util.ArrayList;
|
||
import java.util.Date;
|
|||
import java.util.HashMap;
|
|||
import java.util.LinkedList;
|
|||
import java.util.List;
|
|||
import java.util.Map;
|
|||
|
|||
|
import org.json.JSONArray;
|
||
|
|||
|
import org.mozilla.gecko.db.BrowserContract.Bookmarks;
|
||
|
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||
|
import org.mozilla.gecko.db.BrowserDB;
|
||
import org.mozilla.gecko.db.BrowserDB.URLColumns;
|
|||
|
|||
public class AwesomeBarTabs extends TabHost {
|
|||
private static final String LOGTAG = "GeckoAwesomeBarTabs";
|
|||
|
|||
private Context mContext;
|
|||
|
private boolean mInflated;
|
||
|
private LayoutInflater mInflater;
|
||
private OnUrlOpenListener mUrlOpenListener;
|
|||
|
|||
|
private AllPagesTab mAllPagesTab;
|
||
|
public BookmarksTab mBookmarksTab;
|
||
|
public HistoryTab mHistoryTab;
|
||
|
|||
// FIXME: This value should probably come from a
|
|||
// prefs key (just like XUL-based fennec)
|
|||
private static final int MAX_RESULTS = 100;
|
|||
|
|||
public interface OnUrlOpenListener {
|
|||
|
public void onUrlOpen(String url);
|
||
|
public void onSearch(String engine, String text);
|
||
public void onEditSuggestion(String suggestion);
|
|||
}
|
|||
|
|||
// This method checks to see if we're in a bookmark sub-folder. If we are,
|
|||
// it will go up a level and return true. Otherwise it will return false.
|
|||
public boolean onBackPressed() {
|
|||
|
// If the soft keyboard is visible in the bookmarks or history tab, the user
|
||
// must have explictly brought it up, so we should try hiding it instead of
|
|||
// exiting the activity or going up a bookmarks folder level.
|
|||
|
if (getCurrentTabTag().equals(mBookmarksTab.getTag()) || getCurrentTabTag().equals(mHistoryTab.getTag())) {
|
||
|
View tabView = getCurrentTabView();
|
||
if (hideSoftInput(tabView))
|
|||
return true;
|
|||
}
|
|||
|
|||
// If we're not in the bookmarks tab, we have nothing to do. We should
|
|||
// also return false if mBookmarksAdapter hasn't been initialized yet.
|
|||
|
if (!getCurrentTabTag().equals(mBookmarksTab.getTag()))
|
||
return false;
|
|||
|
|||
|
return mBookmarksTab.moveToParentFolder();
|
||
}
|
|||
|
|||
public AwesomeBarTabs(Context context, AttributeSet attrs) {
|
|||
super(context, attrs);
|
|||
|
|||
Log.d(LOGTAG, "Creating AwesomeBarTabs");
|
|||
|
|||
mContext = context;
|
|||
|
mInflated = false;
|
||
|
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||
|
}
|
||
|
|||
@Override
|
|||
protected void onFinishInflate() {
|
|||
super.onFinishInflate();
|
|||
|
|||
|
// HACK: Without this, the onFinishInflate is called twice
|
||
// This issue is due to a bug when Android inflates a layout with a
|
|||
// parent. Fixed in Honeycomb
|
|||
if (mInflated)
|
|||
return;
|
|||
|
|||
|
mInflated = true;
|
||
|
|||
// This should be called before adding any tabs
|
|||
// to the TabHost.
|
|||
setup();
|
|||
|
|||
addAllPagesTab();
|
|||
addBookmarksTab();
|
|||
addHistoryTab();
|
|||
|
|||
// Initialize "App Pages" list with no filter
|
|||
filter("");
|
|||
}
|
|||
|
|||
|
private TabSpec addAwesomeTab(String id, int titleId, TabHost.TabContentFactory factory) {
|
||
TabSpec tab = getTabSpec(id, titleId);
|
|||
tab.setContent(factory);
|
|||
addTab(tab);
|
|||
|
|||
return tab;
|
|||
}
|
|||
|
|||
private TabSpec getTabSpec(String id, int titleId) {
|
|||
TabSpec tab = newTabSpec(id);
|
|||
|
|||
|
View indicatorView = mInflater.inflate(R.layout.awesomebar_tab_indicator, null);
|
||
Drawable background = indicatorView.getBackground();
|
|||
|
try {
|
||
background.setColorFilter(new LightingColorFilter(Color.WHITE, 0xFFFF9500));
|
|||
|
} catch (Exception e) {
|
||
Log.d(LOGTAG, "background.setColorFilter failed " + e);
|
|||
}
|
|||
TextView title = (TextView) indicatorView.findViewById(R.id.title);
|
|||
title.setText(titleId);
|
|||
|
|||
tab.setIndicator(indicatorView);
|
|||
|
|||
return tab;
|
|||
}
|
|||
|
|||
private void addAllPagesTab() {
|
|||
Log.d(LOGTAG, "Creating All Pages tab");
|
|||
|
|||
|
mAllPagesTab = new AllPagesTab(mContext);
|
||
addAwesomeTab(mAllPagesTab.getTag(),
|
|||
mAllPagesTab.getTitleStringId(),
|
|||
mAllPagesTab.getFactory());
|
|||
}
|
|||
|
|||
private void addBookmarksTab() {
|
|||
Log.d(LOGTAG, "Creating Bookmarks tab");
|
|||
|
|||
|
mBookmarksTab = new BookmarksTab(mContext);
|
||
addAwesomeTab(mBookmarksTab.getTag(),
|
|||
mBookmarksTab.getTitleStringId(),
|
|||
mBookmarksTab.getFactory());
|
|||
}
|
|||
|
|||
private void addHistoryTab() {
|
|||
Log.d(LOGTAG, "Creating History tab");
|
|||
|
|||
|
mHistoryTab = new HistoryTab(mContext);
|
||
addAwesomeTab(mHistoryTab.getTag(),
|
|||
mHistoryTab.getTitleStringId(),
|
|||
mHistoryTab.getFactory());
|
|||
}
|
|||
|
|||
|
private boolean hideSoftInput(View view) {
|
||
InputMethodManager imm =
|
|||
(InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
|
|||
|
|||
|
return imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||
}
|
|||
|
|||
|
private String getReaderForUrl(String url) {
|
||
// FIXME: still need to define the final way to open items from
|
|||
// reading list. For now, we're using an about:reader page.
|
|||
return "about:reader?url=" + url;
|
|||
}
|
|||
|
|||
public void setOnUrlOpenListener(OnUrlOpenListener listener) {
|
|||
mUrlOpenListener = listener;
|
|||
|
mAllPagesTab.setUrlListener(listener);
|
||
|
mBookmarksTab.setUrlListener(listener);
|
||
|
mHistoryTab.setUrlListener(listener);
|
||
}
|
|||
|
|||
public void destroy() {
|
|||
|
mAllPagesTab.destroy();
|
||
|
mBookmarksTab.destroy();
|
||
|
mHistoryTab.destroy();
|
||
}
|
|||
|
|||
public void filter(String searchTerm) {
|
|||
// Don't let the tab's content steal focus on tab switch
|
|||
setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
|
|||
|
|||
// Ensure the 'All Pages' tab is selected
|
|||
|
setCurrentTabByTag(mAllPagesTab.getTag());
|
||
|
|||
// Restore normal focus behavior on tab host
|
|||
setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
|
|||
|
|||
// The tabs should only be visible if there's no on-going search
|
|||
int tabsVisibility = (searchTerm.length() == 0 ? View.VISIBLE : View.GONE);
|
|||
getTabWidget().setVisibility(tabsVisibility);
|
|||
|
|||
// Perform the actual search
|
|||
|
mAllPagesTab.filter(searchTerm);
|
||
|
}
|
||
|
|||
|
/**
|
||
* Sets suggestions associated with the current suggest engine.
|
|||
* If there is no suggest engine, this does nothing.
|
|||
*/
|
|||
public void setSuggestions(final ArrayList<String> suggestions) {
|
|||
GeckoAppShell.getMainHandler().post(new Runnable() {
|
|||
public void run() {
|
|||
|
mAllPagesTab.setSuggestions(suggestions);
|
||
|
}
|
||
});
|
|||
}
|
|||
|
|||
/**
|
|||
* Sets search engines to be shown for user-entered queries.
|
|||
*/
|
|||
|
public void setSearchEngines(final String suggestEngineName, final JSONArray engines) {
|
||
|
GeckoAppShell.getMainHandler().post(new Runnable() {
|
||
public void run() {
|
|||
|
mAllPagesTab.setSearchEngines(suggestEngineName, engines);
|
||
|
}
|
||
});
|
|||
}
|
|||
|
|
||
|
public boolean isInReadingList() {
|
||
|
return mBookmarksTab.isInReadingList();
|
||
|
}
|
||
|
|||
|
@Override
|
||
public boolean onInterceptTouchEvent(MotionEvent ev) {
|
|||
|
// we should only have to hide the soft keyboard once - when the user
|
||
// initially touches the screen
|
|||
if (ev.getAction() == MotionEvent.ACTION_DOWN)
|
|||
hideSoftInput(this);
|
|||
|
|
||
// the android docs make no sense, but returning false will cause this and other
|
|||
// motion events to be sent to the view the user tapped on
|
|||
return false;
|
|||
}
|
|||
}
|