Bookmarks and history removed

This commit is contained in:
Philipp Crocoll 2013-09-26 01:59:35 +02:00
parent 848f99562c
commit 5c49a7fcb1
26 changed files with 11 additions and 3632 deletions

View File

@ -23,25 +23,6 @@
android:drawableLeft="?attr/afc_button_home"
android:text="@string/afc_cmd_home" />
<TextView
android:id="@+id/afc_textview_bookmarks"
style="@style/afc_home_button_navigators"
android:layout_below="@id/afc_textview_home"
android:drawableLeft="@drawable/afc_bookmarks_dark"
android:text="@string/afc_title_bookmarks" />
<View
android:id="@+id/afc_viewgroup_bookmarks_view_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/afc_viewgroup_button_locations_bottom_divider_height"
android:layout_below="@id/afc_textview_bookmarks"
android:background="@color/afc_border_line_dark" />
<FrameLayout
android:id="@+id/afc_fragment_bookmarks"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/afc_viewgroup_bookmarks_view_divider" />
</RelativeLayout>
<View
@ -156,6 +137,7 @@
layout="@layout/afc_view_loading" />
</RelativeLayout>
<LinearLayout
android:id="@+id/afc_viewgroup_footer_container"
style="?attr/afc_button_bar_style"

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/afc_color_list_group_view_background" >
<TextView
android:id="@+id/afc_textview_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:ellipsize="middle"
android:gravity="center"
android:maxLines="@integer/afc_bookmark_filename_max_lines"
android:padding="@dimen/afc_10sp"
android:textIsSelectable="false"
android:textStyle="bold" />
</RelativeLayout>

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_margin="@dimen/afc_5dp"
android:layout_weight="1"
android:orientation="vertical" >
<TextView
android:id="@+id/afc_text_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="middle"
android:gravity="center_vertical"
android:maxLines="@integer/afc_bookmark_filename_max_lines"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textIsSelectable="false" >
</TextView>
<TextView
android:id="@+id/afc_text_path"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/afc_2dp"
android:ellipsize="middle"
android:maxLines="@integer/afc_bookmark_pathname_max_lines"
android:textIsSelectable="false"
android:visibility="gone" >
</TextView>
</LinearLayout>
<CheckBox
android:id="@+id/afc_checkbox"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="top"
android:focusable="false"
android:focusableInTouchMode="false"
android:gravity="top"
android:padding="@dimen/afc_5dp"
android:visibility="gone" />
</LinearLayout>

View File

@ -8,22 +8,11 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:afc="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/afc_menuitem_bookmarks"
afc:showAsAction="ifRoom"
android:icon="?attr/afc_ic_menu_bookmarks"
android:title="@string/afc_title_bookmarks"/>
<item
android:id="@+id/afc_menuitem_home"
afc:showAsAction="ifRoom"
android:icon="?attr/afc_ic_menu_home"
android:title="@string/afc_cmd_home"/>
<item
android:id="@+id/afc_menuitem_history"
afc:showAsAction="ifRoom"
android:icon="@android:drawable/ic_menu_recent_history"
android:title="@string/afc_history"/>
<item
android:id="@+id/afc_menuitem_sort"
afc:showAsAction="ifRoom"

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (c) 2012 Hai Bison
See the file LICENSE at the root directory of this project for copying
permission.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/afc_menuitem_clear"
android:icon="@android:drawable/ic_menu_close_clear_cancel"
android:showAsAction="ifRoom|withText"
android:title="@string/afc_cmd_clear"/>
</menu>

View File

@ -14,7 +14,6 @@
<resources>
<string name="afc_cmd_add_to_bookmarks">Añadir a favoritos</string>
<string name="afc_cmd_advanced_selection_all">Todos</string>
<string name="afc_cmd_advanced_selection_invert">Invertir selección</string>
<string name="afc_cmd_advanced_selection_none">Ninguno</string>
@ -43,12 +42,10 @@
<string name="afc_history">Historia</string>
<string name="afc_msg_app_doesnot_have_permission_to_create_files">La aplicación no tiene permisos para crear ficheros/directorios</string>
<string name="afc_msg_app_doesnot_have_permission_to_delete_files">La aplicación no tiene permisos para eliminar ficheros/directorios</string>
<string name="afc_msg_bookmark_name_is_invalid">Nombre de favorito no válido</string>
<string name="afc_msg_cancelled">Cancelado</string>
<string name="afc_msg_cannot_connect_to_file_provider_service">No se puede conectar con el servicio proveedor de ficheros</string>
<string name="afc_msg_cannot_create_new_folder_here">No se puede crear un nuevo directorio aquí</string>
<string name="afc_msg_cannot_save_a_file_here">No se puede guardar un archivo aquí</string>
<string name="afc_msg_confirm_clear_all_bookmarks">¿Seguro que deseas borrar todos los favoritos?</string>
<string name="afc_msg_confirm_clear_history">¿Está seguro que desea borrar el historial?</string>
<string name="afc_msg_done">Hecho</string>
<string name="afc_msg_empty">Vacío</string>
@ -71,15 +68,11 @@
<string name="afc_root">Raiz</string>
<string name="afc_title_advanced_selection">Seleccionar…</string>
<string name="afc_title_alert">Alerta</string>
<string name="afc_title_bookmark_manager">Administrador de favoritos</string>
<string name="afc_title_bookmarks">Favoritos</string>
<string name="afc_title_confirmation">Confirmación</string>
<string name="afc_title_date">Fecha</string>
<string name="afc_title_error">Error</string>
<string name="afc_title_history">Historial</string>
<string name="afc_title_info">Información</string>
<string name="afc_title_name">Nombre</string>
<string name="afc_title_new_bookmark">Nuevo favorito</string>
<string name="afc_title_rename">Renombrar…</string>
<string name="afc_title_save_as">Guardar como…</string>
<string name="afc_title_size">Tamaño</string>

View File

@ -9,7 +9,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Afc.BaseThemeHelper.Dark" parent="@style/Afc.BaseTheme.Dark">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks_light</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home_light</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview_light</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview_light</item>
@ -33,7 +32,6 @@
<style name="Afc.BaseTheme.Dialog.Dark" parent="@android:style/Theme.Holo.Dialog"></style>
<style name="Afc.BaseThemeHelper.Dialog.Dark" parent="@style/Afc.BaseTheme.Dialog.Dark">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks_light</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home_light</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview_light</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview_light</item>

View File

@ -9,7 +9,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Afc.BaseThemeHelper.Light" parent="@style/Afc.BaseTheme.Light">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks_light</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home_light</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview_light</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview_light</item>
@ -32,7 +31,6 @@
<style name="Afc.BaseTheme.Dialog.Light" parent="@android:style/Theme.Holo.Light.Dialog"></style>
<style name="Afc.BaseThemeHelper.Dialog.Light" parent="@style/Afc.BaseTheme.Dialog.Light">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks_light</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home_light</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview_light</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview_light</item>

View File

@ -11,7 +11,6 @@
<style name="Afc.BaseTheme.Dark" parent="@style/Theme.AppCompat"></style>
<style name="Afc.BaseThemeHelper.Dark" parent="@style/Afc.BaseTheme.Dark">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks_light</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home_light</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview_light</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview_light</item>

View File

@ -11,7 +11,6 @@
<style name="Afc.BaseTheme.Light" parent="@style/Theme.AppCompat.Light.DarkActionBar"></style>
<style name="Afc.BaseThemeHelper.Light" parent="@style/Afc.BaseTheme.Light">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks_light</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home_light</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview_light</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview_light</item>

View File

@ -8,7 +8,6 @@
<resources>
<string name="afc_cmd_add_to_bookmarks">Thêm vô danh sách ưa thích…</string>
<string name="afc_cmd_advanced_selection_all">Tất cả</string>
<string name="afc_cmd_advanced_selection_invert">Đảo lựa chọn</string>
<string name="afc_cmd_advanced_selection_none">Không chọn</string>
@ -37,12 +36,10 @@
<string name="afc_history">Lịch sử</string>
<string name="afc_msg_app_doesnot_have_permission_to_create_files">Ứng dụng này không có quyền tạo mới tập tin/ thư mục</string>
<string name="afc_msg_app_doesnot_have_permission_to_delete_files">Ứng dụng này không có quyền xóa tập tin/ thư mục</string>
<string name="afc_msg_bookmark_name_is_invalid">Tên không hợp lệ</string>
<string name="afc_msg_cancelled">Hủy bỏ</string>
<string name="afc_msg_cannot_connect_to_file_provider_service">Không thể kết nối đến dịch vụ cung cấp tập tin</string>
<string name="afc_msg_cannot_create_new_folder_here">Không thể tạo thư mục mới ở đây</string>
<string name="afc_msg_cannot_save_a_file_here">Không thể lưu tập tin ở đây</string>
<string name="afc_msg_confirm_clear_all_bookmarks">Bạn có chắc muốn xóa hết danh sách ưa thích không?</string>
<string name="afc_msg_confirm_clear_history">Bạn có chắc muốn xoá hết lịch sử không?</string>
<string name="afc_msg_done">Xong</string>
<string name="afc_msg_empty">Không có gì</string>
@ -64,15 +61,12 @@
<string name="afc_pmsg_xxx_items">%1$,d lựa chọn</string>
<string name="afc_title_advanced_selection">Chọn…</string>
<string name="afc_title_alert">Cảnh báo</string>
<string name="afc_title_bookmark_manager">Quản lý danh sách ưa thích</string>
<string name="afc_title_bookmarks">Ưa thích</string>
<string name="afc_title_confirmation">Xác nhận</string>
<string name="afc_title_date">Ngày tháng</string>
<string name="afc_title_error">Lỗi</string>
<string name="afc_title_history">Lịch sử</string>
<string name="afc_title_info">Thông tin</string>
<string name="afc_title_name">Tên</string>
<string name="afc_title_new_bookmark">Thêm thư mục ưa thích</string>
<string name="afc_title_rename">Đổi tên…</string>
<string name="afc_title_save_as">Lưu…</string>
<string name="afc_title_size">Kích thước</string>

View File

@ -27,7 +27,6 @@
<attr name="afc_theme_dialog" format="reference" />
<attr name="afc_button_home" format="reference" />
<attr name="afc_ic_menu_bookmarks" format="reference" />
<attr name="afc_ic_menu_home" format="reference" />
<attr name="afc_ic_menu_gridview" format="reference" />
<attr name="afc_ic_menu_listview" format="reference" />

View File

@ -8,11 +8,11 @@
<resources>
<string name="afc_lib_name">android-filechooser</string>
<string name="afc_lib_name" translatable="false">android-filechooser</string>
<integer name="afc_lib_version_code">51</integer>
<string name="afc_lib_version_name">5.4</string>
<string name="afc_lib_version_name" translatable="false">5.4</string>
<bool name="afc_is_large_screen">false</bool>

View File

@ -8,8 +8,6 @@
<resources>
<integer name="afc_bookmark_filename_max_lines">1</integer>
<integer name="afc_bookmark_pathname_max_lines">3</integer>
<integer name="afc_history_filename_max_lines">2</integer>
<integer name="afc_history_pathname_max_lines">3</integer>
<integer name="afc_afc_search_view_delay_time_submission">999</integer>

View File

@ -8,13 +8,13 @@
<resources>
<string name="afc_pkey_display_view_type">afc.display.view_type</string>
<string name="afc_pkey_display_sort_type">afc.display.sort_type</string>
<string name="afc_pkey_display_sort_ascending">afc.display.sort_ascending</string>
<string name="afc_pkey_display_show_time_for_old_days_this_year">afc.display.show_time_for_old_days_this_year</string>
<string name="afc_pkey_display_show_time_for_old_days">afc.display.show_time_for_old_days</string>
<string name="afc_pkey_display_remember_last_location">afc.display.remember_last_location</string>
<string name="afc_pkey_display_last_location">afc.display.last_location</string>
<string name="afc_pkey_display_view_type" translatable="false">afc.display.view_type</string>
<string name="afc_pkey_display_sort_type" translatable="false">afc.display.sort_type</string>
<string name="afc_pkey_display_sort_ascending" translatable="false">afc.display.sort_ascending</string>
<string name="afc_pkey_display_show_time_for_old_days_this_year" translatable="false">afc.display.show_time_for_old_days_this_year</string>
<string name="afc_pkey_display_show_time_for_old_days" translatable="false">afc.display.show_time_for_old_days</string>
<string name="afc_pkey_display_remember_last_location" translatable="false">afc.display.remember_last_location</string>
<string name="afc_pkey_display_last_location" translatable="false">afc.display.last_location</string>
<integer name="afc_pkey_display_view_type_def">0</integer>
<integer name="afc_pkey_display_sort_type_def">0</integer>

View File

@ -8,7 +8,6 @@
<resources>
<string name="afc_cmd_add_to_bookmarks">Add to bookmarks…</string>
<string name="afc_cmd_advanced_selection_all">All</string>
<string name="afc_cmd_advanced_selection_invert">Invert selection</string>
<string name="afc_cmd_advanced_selection_none">None</string>
@ -37,12 +36,10 @@
<string name="afc_history">History</string>
<string name="afc_msg_app_doesnot_have_permission_to_create_files">This application does not have permission to create files/ folders</string>
<string name="afc_msg_app_doesnot_have_permission_to_delete_files">This application does not have permission to delete files/ folders</string>
<string name="afc_msg_bookmark_name_is_invalid">Bookmark name is invalid</string>
<string name="afc_msg_cancelled">Cancelled</string>
<string name="afc_msg_cannot_connect_to_file_provider_service">Cannot connect to file provider service</string>
<string name="afc_msg_cannot_create_new_folder_here">Cannot create new folder here</string>
<string name="afc_msg_cannot_save_a_file_here">Cannot save a file here</string>
<string name="afc_msg_confirm_clear_all_bookmarks">Do you really want to clear all bookmarks?</string>
<string name="afc_msg_confirm_clear_history">Are you sure you want to clear history?</string>
<string name="afc_msg_done">Done</string>
<string name="afc_msg_empty">Empty</string>
@ -65,15 +62,11 @@
<string name="afc_root">Root</string>
<string name="afc_title_advanced_selection">Select…</string>
<string name="afc_title_alert">Alert</string>
<string name="afc_title_bookmark_manager">Bookmark manager</string>
<string name="afc_title_bookmarks">Bookmarks</string>
<string name="afc_title_confirmation">Confirmation</string>
<string name="afc_title_date">Date</string>
<string name="afc_title_error">Error</string>
<string name="afc_title_history">History</string>
<string name="afc_title_info">Info</string>
<string name="afc_title_name">Name</string>
<string name="afc_title_new_bookmark">New bookmark</string>
<string name="afc_title_rename">Rename…</string>
<string name="afc_title_save_as">Save as…</string>
<string name="afc_title_size">Size</string>

View File

@ -19,7 +19,6 @@
<style name="Afc.BaseTheme.Dark" parent="@android:style/Theme"></style>
<style name="Afc.BaseThemeHelper.Dark" parent="@style/Afc.BaseTheme.Dark">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview</item>
@ -60,7 +59,6 @@
<!-- android-filechooser -->
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview</item>

View File

@ -19,7 +19,6 @@
<style name="Afc.BaseTheme.Light" parent="@android:style/Theme.Light"></style>
<style name="Afc.BaseThemeHelper.Light" parent="@style/Afc.BaseTheme.Light">
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview</item>
@ -59,7 +58,6 @@
<!-- android-filechooser -->
<item name="afc_ic_menu_bookmarks">@drawable/afc_ic_menu_bookmarks</item>
<item name="afc_ic_menu_home">@drawable/afc_ic_menu_home</item>
<item name="afc_ic_menu_gridview">@drawable/afc_ic_menu_gridview</item>
<item name="afc_ic_menu_listview">@drawable/afc_ic_menu_listview</item>

View File

@ -28,8 +28,6 @@ import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.Dlg;
import group.pals.android.lib.ui.filechooser.utils.ui.LoadingDialog;
import group.pals.android.lib.ui.filechooser.utils.ui.Ui;
import group.pals.android.lib.ui.filechooser.utils.ui.bookmark.BookmarkFragment;
import group.pals.android.lib.ui.filechooser.utils.ui.history.HistoryFragment;
import java.util.ArrayList;
import java.util.Calendar;
@ -220,8 +218,6 @@ public class FragmentFiles extends Fragment implements
*/
private View mBtnGoHome;
private View mBtnBookmarkManager;
private BookmarkFragment mBookmarkFragment;
private HorizontalScrollView mViewLocationsContainer;
private ViewGroup mViewLocations;
private View mViewGroupFiles;
@ -304,8 +300,6 @@ public class FragmentFiles extends Fragment implements
*/
mBtnGoHome = rootView.findViewById(R.id.afc_textview_home);
mBtnBookmarkManager = rootView
.findViewById(R.id.afc_textview_bookmarks);
mViewGoBack = (ImageView) rootView
.findViewById(R.id.afc_button_go_back);
mViewGoForward = (ImageView) rootView
@ -326,28 +320,6 @@ public class FragmentFiles extends Fragment implements
.findViewById(R.id.afc_textview_saveas_filename);
mBtnOk = (Button) rootView.findViewById(R.id.afc_button_ok);
/*
* INIT CONTROLS
*/
/*
* Load BookmarkFragment.
*/
View viewBookmarks = rootView.findViewById(R.id.afc_fragment_bookmarks);
if (viewBookmarks != null) {
mBookmarkFragment = (BookmarkFragment) getChildFragmentManager()
.findFragmentById(R.id.afc_fragment_bookmarks);
if (mBookmarkFragment == null) {
mBookmarkFragment = BookmarkFragment.newInstance(false);
mBookmarkFragment
.setOnBookmarkItemClickListener(mBookmarkFragmentOnBookmarkItemClickListener);
getChildFragmentManager().beginTransaction()
.add(R.id.afc_fragment_bookmarks, mBookmarkFragment)
.commit();
}
}// if
return rootView;
}// onCreateView()
@ -441,10 +413,6 @@ public class FragmentFiles extends Fragment implements
doSwitchViewType();
else if (item.getItemId() == R.id.afc_menuitem_home)
doGoHome();
else if (item.getItemId() == R.id.afc_menuitem_history)
doShowHistoryManager();
else if (item.getItemId() == R.id.afc_menuitem_bookmarks)
doShowBookmarkManager();
else
return false;
@ -693,9 +661,6 @@ public class FragmentFiles extends Fragment implements
private void setupHeader() {
if (mBtnGoHome != null)
mBtnGoHome.setOnClickListener(mBtnGoHomeOnClickListener);
if (mBtnBookmarkManager != null)
mBtnBookmarkManager
.setOnClickListener(mBtnBookmarkManagerOnClickListener);
if (mIsSaveDialog) {
getActivity().setTitle(R.string.afc_title_save_as);
@ -728,8 +693,7 @@ public class FragmentFiles extends Fragment implements
mViewGoForward.setEnabled(false);
mViewGoForward.setOnClickListener(mBtnGoForwardOnClickListener);
for (ImageView v : new ImageView[] { mViewGoBack, mViewGoForward })
v.setOnLongClickListener(mBtnGoBackForwardOnLongClickListener);
}// setupHeader()
/**
@ -1194,62 +1158,6 @@ public class FragmentFiles extends Fragment implements
goTo(mRoot);
}// doGoHome()
/**
* Shows bookmark manager.
*/
private void doShowBookmarkManager() {
BookmarkFragment bf = BookmarkFragment.newInstance(true);
bf.setOnBookmarkItemClickListener(mBookmarkFragmentOnBookmarkItemClickListener);
bf.show(getChildFragmentManager().beginTransaction(),
BookmarkFragment.class.getName());
}// doShowBookmarkManager()
/**
* Shows history manager.
*/
private void doShowHistoryManager() {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "doShowHistoryManager()");
// Create and show the dialog.
final HistoryFragment fragment = HistoryFragment.newInstance();
fragment.setOnHistoryItemClickListener(new HistoryFragment.OnHistoryItemClickListener() {
@Override
public void onItemClick(String providerId, final Uri uri) {
/*
* TODO what to do with `providerId`?
*/
/*
* Check if `uri` is in internal list, then use it instead of
* that.
*/
if (!mHistory.find(new HistoryFilter<Uri>() {
@Override
public boolean accept(Uri item) {
if (uri.equals(item)) {
goTo(item);
return true;
}
return false;
}// accept()
}, false))
goTo(uri);
}// onItemClick()
});
/*
* DialogFragment.show() will take care of adding the fragment in a
* transaction. We also want to remove any currently showing dialog, so
* make our own transaction and take care of that here.
*/
fragment.show(getChildFragmentManager().beginTransaction(),
HistoryFragment.class.getName());
}// doShowHistoryManager()
private static final int[] BUTTON_SORT_IDS = {
R.id.afc_button_sort_by_name_asc,
R.id.afc_button_sort_by_name_desc,
@ -1948,15 +1856,6 @@ public class FragmentFiles extends Fragment implements
}// onClick()
};// mBtnGoHomeOnClickListener
private final View.OnClickListener mBtnBookmarkManagerOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mBookmarkFragment != null)
mBookmarkFragment.setEditor(!mBookmarkFragment.isEditor());
}// onClick()
};// mBtnBookmarkManagerOnClickListener
private final View.OnClickListener mBtnGoBackOnClickListener = new View.OnClickListener() {
@Override
@ -2023,15 +1922,6 @@ public class FragmentFiles extends Fragment implements
}// onClick()
};// mBtnGoForwardOnClickListener
private final View.OnLongClickListener mBtnGoBackForwardOnLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
doShowHistoryManager();
return true;
}// onLongClick()
};// mBtnGoBackForwardOnLongClickListener
private final TextView.OnEditorActionListener mTxtFilenameOnEditorActionListener = new TextView.OnEditorActionListener() {
@Override
@ -2067,32 +1957,6 @@ public class FragmentFiles extends Fragment implements
* FRAGMENT LISTENERS
*/
private final BookmarkFragment.OnBookmarkItemClickListener mBookmarkFragmentOnBookmarkItemClickListener = new BookmarkFragment.OnBookmarkItemClickListener() {
@Override
public void onItemClick(String providerId, final Uri uri) {
/*
* TODO what to do with `providerId`?
*/
/*
* Check if `uri` is in internal list, then use it instead of that.
*/
if (!mHistory.find(new HistoryFilter<Uri>() {
@Override
public boolean accept(Uri item) {
if (uri.equals(item)) {
goTo(item);
return true;
}
return false;
}// accept()
}, false))
goTo(uri);
}// onItemClick()
};// mBookmarkFragmentOnBookmarkItemClickListener
/*
* LISTVIEW HELPER
@ -2167,22 +2031,6 @@ public class FragmentFiles extends Fragment implements
final Uri uri = BaseFileProviderUtils.getUri(cursor);
final String name = BaseFileProviderUtils.getFileName(cursor);
ContextMenuUtils.showContextMenu(getActivity(), 0, 0,
new Integer[] { R.string.afc_cmd_add_to_bookmarks },
new ContextMenuUtils.OnMenuItemClickListener() {
@Override
public void onClick(final int resId) {
if (resId == R.string.afc_cmd_add_to_bookmarks) {
BookmarkFragment
.doEnterNewNameOrRenameBookmark(
getActivity(),
BaseFileProviderUtils.getProviderId(uri
.getAuthority()), -1,
uri, name);
}
}// onClick()
});
}// onBuildOptionsMenu()
@Override

View File

@ -1,124 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.providers.bookmark;
import android.content.Context;
import android.net.Uri;
import group.pals.android.lib.ui.filechooser.providers.BaseColumns;
import group.pals.android.lib.ui.filechooser.providers.ProviderUtils;
/**
* Bookmark contract.
*
* @author Hai Bison
* @since v5.1 beta
*/
public final class BookmarkContract implements BaseColumns {
/**
* The raw authority.
*/
private static final String AUTHORITY = "android-filechooser.bookmark";
/**
* Gets the authority of this provider.
*
* @param context
* the context.
* @return the authority.
*/
public static final String getAuthority(Context context) {
return context.getPackageName() + "." + AUTHORITY;
}// getAuthority()
// This class cannot be instantiated
private BookmarkContract() {
}
/**
* The table name offered by this provider.
*/
public static final String TABLE_NAME = "bookmarks";
/*
* URI definitions.
*/
/**
* Path parts for the URIs.
*/
/**
* Path part for the Bookmark URI.
*/
public static final String PATH_BOOKMARKS = "bookmarks";
/**
* The content:// style URL for this table.
*/
public static final Uri genContentUri(Context context) {
return Uri.parse(ProviderUtils.SCHEME + getAuthority(context) + "/"
+ PATH_BOOKMARKS);
}// genContentUri()
/**
* The content URI base for a single Bookmark item. Callers must append a
* numeric Bookmark id to this Uri to retrieve a Bookmark item.
*/
public static final Uri genContentIdUriBase(Context context) {
return Uri.parse(ProviderUtils.SCHEME + getAuthority(context) + "/"
+ PATH_BOOKMARKS + "/");
}// genContentIdUriBase()
/*
* MIME type definitions
*/
/**
* The MIME type of {@link #_ContentUri} providing a directory of Bookmark
* items.
*/
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.android-filechooser.bookmarks";
/**
* The MIME type of a {@link #_ContentUri} sub-directory of a single
* Bookmark item.
*/
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.android-filechooser.bookmarks";
/**
* The default sort order for this table.
*/
public static final String DEFAULT_SORT_ORDER = COLUMN_MODIFICATION_TIME
+ " DESC";
/*
* Column definitions
*/
/**
* Column name for the URI of bookmark.
* <p/>
* Type: {@code String}
*/
public static final String COLUMN_URI = "uri";
/**
* Column name for the name of bookmark.
* <p/>
* Type: {@code String}
*/
public static final String COLUMN_NAME = "name";
/**
* Column name for the ID of bookmark's provider ID.
* <p/>
* Type: {@code String}
*/
public static final String COLUMN_PROVIDER_ID = "provider_id";
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.providers.bookmark;
import group.pals.android.lib.ui.filechooser.prefs.Prefs;
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
/**
* Database for bookmark.
*
* @author Hai Bison
* @since v5.1 beta
*/
public class BookmarkHelper extends SQLiteOpenHelper {
@SuppressWarnings("unused")
private static final String CLASSNAME = BookmarkHelper.class.getName();
private static final String DB_FILENAME = "Bookmarks.sqlite";
private static final int DB_VERSION = 1;
// Database creation SQL statements
/**
* @since v5.1 beta
*/
private static final String PATTERN_DB_CREATOR = String
.format("CREATE VIRTUAL TABLE " + BookmarkContract.TABLE_NAME
+ " USING %%s(" + BookmarkContract.COLUMN_CREATE_TIME + ","
+ BookmarkContract.COLUMN_MODIFICATION_TIME + ","
+ BookmarkContract.COLUMN_PROVIDER_ID + ","
+ BookmarkContract.COLUMN_URI + ","
+ BookmarkContract.COLUMN_NAME + ",tokenize=porter);");
public BookmarkHelper(Context context) {
// always use application context
super(context.getApplicationContext(), Prefs.genDatabaseFilename(
context, DB_FILENAME), null, DB_VERSION);
}// BookmarkHelper()
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(String
.format(PATTERN_DB_CREATOR,
Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? DbUtils.SQLITE_FTS3
: DbUtils.SQLITE_FTS4));
}// onCreate()
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO
}// onUpgrade()
}

View File

@ -1,362 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.providers.bookmark;
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
/**
* Bookmark provider.
*
* @author Hai Bison
* @since v5.1 beta
*/
public class BookmarkProvider extends ContentProvider {
@SuppressWarnings("unused")
private static final String CLASSNAME = BookmarkProvider.class.getName();
/*
* Constants used by the Uri matcher to choose an action based on the
* pattern of the incoming URI.
*/
/**
* The incoming URI matches the Bookmark URI pattern.
*/
private static final int URI_BOOKMARKS = 1;
/**
* The incoming URI matches the Bookmark ID URI pattern.
*/
private static final int URI_BOOKMARK_ID = 2;
/**
* A {@link UriMatcher} instance.
*/
private static final UriMatcher URI_MATCHER = new UriMatcher(
UriMatcher.NO_MATCH);
private static final Map<String, String> MAP_COLUMNS = new HashMap<String, String>();
static {
MAP_COLUMNS.put(DbUtils.SQLITE_FTS_COLUMN_ROW_ID,
DbUtils.SQLITE_FTS_COLUMN_ROW_ID + " AS "
+ BookmarkContract._ID);
MAP_COLUMNS.put(BookmarkContract.COLUMN_NAME,
BookmarkContract.COLUMN_NAME);
MAP_COLUMNS.put(BookmarkContract.COLUMN_PROVIDER_ID,
BookmarkContract.COLUMN_PROVIDER_ID);
MAP_COLUMNS.put(BookmarkContract.COLUMN_URI,
BookmarkContract.COLUMN_URI);
MAP_COLUMNS.put(BookmarkContract.COLUMN_CREATE_TIME,
BookmarkContract.COLUMN_CREATE_TIME);
MAP_COLUMNS.put(BookmarkContract.COLUMN_MODIFICATION_TIME,
BookmarkContract.COLUMN_MODIFICATION_TIME);
}// static
private BookmarkHelper mBookmarkHelper;
@Override
public boolean onCreate() {
mBookmarkHelper = new BookmarkHelper(getContext());
URI_MATCHER.addURI(BookmarkContract.getAuthority(getContext()),
BookmarkContract.PATH_BOOKMARKS, URI_BOOKMARKS);
URI_MATCHER.addURI(BookmarkContract.getAuthority(getContext()),
BookmarkContract.PATH_BOOKMARKS + "/#", URI_BOOKMARK_ID);
return true;
}// onCreate()
@Override
public String getType(Uri uri) {
/*
* Chooses the MIME type based on the incoming URI pattern.
*/
switch (URI_MATCHER.match(uri)) {
case URI_BOOKMARKS:
return BookmarkContract.CONTENT_TYPE;
case URI_BOOKMARK_ID:
return BookmarkContract.CONTENT_ITEM_TYPE;
default:
throw new IllegalArgumentException("UNKNOWN URI " + uri);
}
}// getType()
@Override
public synchronized int delete(Uri uri, String selection,
String[] selectionArgs) {
// Opens the database object in "write" mode.
SQLiteDatabase db = mBookmarkHelper.getWritableDatabase();
String finalWhere;
int count;
// Does the delete based on the incoming URI pattern.
switch (URI_MATCHER.match(uri)) {
/*
* If the incoming pattern matches the general pattern for Bookmark
* items, does a delete based on the incoming "where" columns and
* arguments.
*/
case URI_BOOKMARKS: {
count = db.delete(BookmarkContract.TABLE_NAME, selection,
selectionArgs);
break;
}// URI_BOOKMARKS
/*
* If the incoming URI matches a single note ID, does the delete based
* on the incoming data, but modifies the where clause to restrict it to
* the particular Bookmark item ID.
*/
case URI_BOOKMARK_ID: {
/*
* Starts a final WHERE clause by restricting it to the desired
* Bookmark item ID.
*/
finalWhere = DbUtils.SQLITE_FTS_COLUMN_ROW_ID + " = "
+ uri.getLastPathSegment();
/*
* If there were additional selection criteria, append them to the
* final WHERE clause
*/
if (selection != null)
finalWhere = finalWhere + " AND " + selection;
// Performs the delete.
count = db.delete(BookmarkContract.TABLE_NAME, finalWhere,
selectionArgs);
break;
}// URI_BOOKMARK_ID
// If the incoming pattern is invalid, throws an exception.
default:
throw new IllegalArgumentException("UNKNOWN URI " + uri);
}
/*
* Gets a handle to the content resolver object for the current context,
* and notifies it that the incoming URI changed. The object passes this
* along to the resolver framework, and observers that have registered
* themselves for the provider are notified.
*/
getContext().getContentResolver().notifyChange(uri, null);
// Returns the number of rows deleted.
return count;
}// delete()
@Override
public synchronized Uri insert(Uri uri, ContentValues values) {
/*
* Validates the incoming URI. Only the full provider URI is allowed for
* inserts.
*/
if (URI_MATCHER.match(uri) != URI_BOOKMARKS)
throw new IllegalArgumentException("UNKNOWN URI " + uri);
// Gets the current time in milliseconds
long now = new Date().getTime();
/*
* If the values map doesn't contain the creation date/ modification
* date, sets the value to the current time.
*/
for (String col : new String[] { BookmarkContract.COLUMN_CREATE_TIME,
BookmarkContract.COLUMN_MODIFICATION_TIME })
if (!values.containsKey(col))
values.put(col, DbUtils.formatNumber(now));
// Opens the database object in "write" mode.
SQLiteDatabase db = mBookmarkHelper.getWritableDatabase();
// Performs the insert and returns the ID of the new note.
long rowId = db.insert(BookmarkContract.TABLE_NAME, null, values);
// If the insert succeeded, the row ID exists.
if (rowId > 0) {
/*
* Creates a URI with the note ID pattern and the new row ID
* appended to it.
*/
Uri noteUri = ContentUris.withAppendedId(
BookmarkContract.genContentIdUriBase(getContext()), rowId);
/*
* Notifies observers registered against this provider that the data
* changed.
*/
getContext().getContentResolver().notifyChange(noteUri, null);
return noteUri;
}
/*
* If the insert didn't succeed, then the rowID is <= 0. Throws an
* exception.
*/
throw new SQLException("Failed to insert row into " + uri);
}// insert()
@Override
public synchronized Cursor query(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(BookmarkContract.TABLE_NAME);
qb.setProjectionMap(MAP_COLUMNS);
SQLiteDatabase db = null;
Cursor cursor = null;
/*
* Choose the projection and adjust the "where" clause based on URI
* pattern-matching.
*/
switch (URI_MATCHER.match(uri)) {
case URI_BOOKMARKS: {
if (Arrays.equals(projection,
new String[] { BookmarkContract._COUNT })) {
db = mBookmarkHelper.getReadableDatabase();
cursor = db.rawQuery(
String.format(
"SELECT COUNT(*) AS %s FROM %s %s",
BookmarkContract._COUNT,
BookmarkContract.TABLE_NAME,
selection != null ? String.format("WHERE %s",
selection) : "").trim(), null);
}
break;
}// URI_BOOKMARKS
/*
* If the incoming URI is for a single Bookmark item identified by its
* ID, chooses the Bookmark item ID projection, and appends
* "_ID = <history-item-ID>" to the where clause, so that it selects
* that single Bookmark item.
*/
case URI_BOOKMARK_ID: {
qb.appendWhere(DbUtils.SQLITE_FTS_COLUMN_ROW_ID + " = "
+ uri.getLastPathSegment());
break;
}// URI_BOOKMARK_ID
default:
throw new IllegalArgumentException("UNKNOWN URI " + uri);
}
if (TextUtils.isEmpty(sortOrder))
sortOrder = BookmarkContract.DEFAULT_SORT_ORDER;
if (db == null) {
/*
* Opens the database object in "read" mode, since no writes need to
* be done.
*/
db = mBookmarkHelper.getReadableDatabase();
/*
* Performs the query. If no problems occur trying to read the
* database, then a Cursor object is returned; otherwise, the cursor
* variable contains null. If no records were selected, then the
* Cursor object is empty, and Cursor.getCount() returns 0.
*/
cursor = qb.query(db, projection, selection, selectionArgs, null,
null, sortOrder);
}
/*
* Tells the Cursor what URI to watch, so it knows when its source data
* changes.
*/
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}// query()
@Override
public synchronized int update(Uri uri, ContentValues values,
String selection, String[] selectionArgs) {
// Opens the database object in "write" mode.
SQLiteDatabase db = mBookmarkHelper.getWritableDatabase();
int count;
String finalWhere;
// Does the update based on the incoming URI pattern
switch (URI_MATCHER.match(uri)) {
/*
* If the incoming URI matches the general Bookmark items pattern, does
* the update based on the incoming data.
*/
case URI_BOOKMARKS: {
// Does the update and returns the number of rows updated.
count = db.update(BookmarkContract.TABLE_NAME, values, selection,
selectionArgs);
break;
}// URI_BOOKMARKS
/*
* If the incoming URI matches a single Bookmark item ID, does the
* update based on the incoming data, but modifies the where clause to
* restrict it to the particular history item ID.
*/
case URI_BOOKMARK_ID: {
/*
* Starts creating the final WHERE clause by restricting it to the
* incoming item ID.
*/
finalWhere = DbUtils.SQLITE_FTS_COLUMN_ROW_ID + " = "
+ uri.getLastPathSegment();
/*
* If there were additional selection criteria, append them to the
* final WHERE clause
*/
if (selection != null)
finalWhere = finalWhere + " AND " + selection;
// Does the update and returns the number of rows updated.
count = db.update(BookmarkContract.TABLE_NAME, values, finalWhere,
selectionArgs);
break;
}// URI_BOOKMARK_ID
// If the incoming pattern is invalid, throws an exception.
default:
throw new IllegalArgumentException("UNKNOWN URI " + uri);
}
/*
* Gets a handle to the content resolver object for the current context,
* and notifies it that the incoming URI changed. The object passes this
* along to the resolver framework, and observers that have registered
* themselves for the provider are notified.
*/
getContext().getContentResolver().notifyChange(uri, null);
// Returns the number of rows updated.
return count;
}// update()
}

View File

@ -1,569 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.utils.ui.bookmark;
import group.pals.android.lib.ui.filechooser.BuildConfig;
import group.pals.android.lib.ui.filechooser.R;
import group.pals.android.lib.ui.filechooser.providers.BaseFileProviderUtils;
import group.pals.android.lib.ui.filechooser.providers.bookmark.BookmarkContract;
import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.Ui;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ResourceCursorTreeAdapter;
import android.widget.TextView;
/**
* Bookmark cursor adapter.
*
* @author Hai Bison
* @since v5.1 beta
*/
public class BookmarkCursorAdapter extends ResourceCursorTreeAdapter {
private static final String CLASSNAME = BookmarkCursorAdapter.class
.getName();
/**
* Advanced selection options: All, None, Invert.
*/
public static final Integer[] ADVANCED_SELECTION_OPTIONS = new Integer[] {
R.string.afc_cmd_advanced_selection_all,
R.string.afc_cmd_advanced_selection_none,
R.string.afc_cmd_advanced_selection_invert };
/**
* The "view holder".
*
* @author Hai Bison
*/
private static class BagGroup {
TextView mTextHeader;
}// BagGroup
/**
* The "view holder".
*
* @author Hai Bison
*/
private static class BagChild {
TextView mTextName;
TextView mTextPath;
CheckBox mCheckBox;
}// BagChild
private static class BagChildInfo {
boolean mChecked = false;
boolean mMarkedAsDeleted = false;
}// BagChildInfo
/**
* This column holds the original position of group cursor in original
* cursor.
* <p/>
* Type: {@code Integer}
*/
private static final String COLUMN_ORG_GROUP_POSITION = "org_group_position";
private static final String[] GROUP_CURSOR_COLUMNS = {
BookmarkContract._ID, BookmarkContract.COLUMN_PROVIDER_ID,
COLUMN_ORG_GROUP_POSITION };
private static final String[] CHILD_CURSOR_COLUMNS = {
BookmarkContract._ID, BookmarkContract.COLUMN_NAME,
BookmarkContract.COLUMN_URI, BookmarkContract.COLUMN_PROVIDER_ID,
BookmarkContract.COLUMN_MODIFICATION_TIME };
/**
* Map of child IDs to {@link BagChildInfo}.
*/
private final SparseArray<BagChildInfo> mSelectedChildrenMap = new SparseArray<BagChildInfo>();
private boolean mEditor;
private Cursor mOrgCursor;
private MatrixCursor mGroupCursor;
private SparseArray<MatrixCursor> mChildrenCursor;
/**
* Creates new instance.
*
* @param context
* {@link Context}.
*/
public BookmarkCursorAdapter(Context context) {
super(context, null, R.layout.afc_view_bookmark_item,
R.layout.afc_view_bookmark_sub_item);
}// BookmarkCursorAdapter()
/**
* Changes new cursor.
* <p/>
* You have to query the items in descending order of modification time.
*
* @param cursor
* the cursor.
* @param notificationUri
* the notification URI.
*/
@Override
public synchronized void changeCursor(Cursor cursor) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "changeCursor()");
if (mOrgCursor != null)
mOrgCursor.close();
mOrgCursor = cursor;
MatrixCursor newGroupCursor = cursor != null ? new MatrixCursor(
GROUP_CURSOR_COLUMNS) : null;
SparseArray<MatrixCursor> newChildrenCursor = cursor != null ? new SparseArray<MatrixCursor>()
: null;
/*
* Build new group cursor.
*/
if (cursor != null && cursor.moveToFirst()) {
String lastProviderId = null;
do {
String providerId = cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID));
if (!providerId.equals(lastProviderId)) {
newGroupCursor
.addRow(new Object[] {
cursor.getInt(cursor
.getColumnIndex(BookmarkContract._ID)),
cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID)),
cursor.getPosition() });
}
lastProviderId = providerId;
} while (cursor.moveToNext());
}
/*
* Clean up children cursor.
*/
if (mChildrenCursor != null) {
for (int i = 0; i < mChildrenCursor.size(); i++)
mChildrenCursor.valueAt(i).close();
mChildrenCursor.clear();
}
/*
* Apply new changes... Note that we don't need to close the old group
* cursor. The call to `super.changeCursor()` will do that.
*/
mGroupCursor = newGroupCursor;
mChildrenCursor = newChildrenCursor;
super.changeCursor(mGroupCursor);
}// changeCursor()
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "getChildrenCursor()");
/*
* Try to find the child cursor in the map. If found then it'd be great
* :-)
*/
int orgGroupPosition = groupCursor.getInt(groupCursor
.getColumnIndex(COLUMN_ORG_GROUP_POSITION));
int idx = mChildrenCursor.indexOfKey(orgGroupPosition);
if (idx >= 0)
return mChildrenCursor.valueAt(idx);
/*
* If not found, create new cursor.
*/
MatrixCursor childrenCursor = new MatrixCursor(CHILD_CURSOR_COLUMNS);
mOrgCursor.moveToPosition(orgGroupPosition);
String providerId = groupCursor.getString(groupCursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID));
do {
childrenCursor
.addRow(new Object[] {
mOrgCursor.getInt(mOrgCursor
.getColumnIndex(BookmarkContract._ID)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(BookmarkContract.COLUMN_NAME)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(BookmarkContract.COLUMN_URI)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(BookmarkContract.COLUMN_MODIFICATION_TIME)) });
} while (mOrgCursor.moveToNext()
&& mOrgCursor
.getString(
mOrgCursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID))
.equals(providerId));
/*
* Put it to the map.
*/
mChildrenCursor.put(orgGroupPosition, childrenCursor);
return childrenCursor;
}// getChildrenCursor()
@Override
protected void bindChildView(View view, Context context, Cursor cursor,
boolean isLastChild) {
final int id = cursor.getInt(cursor
.getColumnIndex(BookmarkContract._ID));
Uri uri = Uri.parse(cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_URI)));
/*
* Child Info
*/
final BagChildInfo childInfo;
if (mSelectedChildrenMap.get(id) == null) {
childInfo = new BagChildInfo();
mSelectedChildrenMap.put(id, childInfo);
} else
childInfo = mSelectedChildrenMap.get(id);
/*
* Child
*/
BagChild bag = (BagChild) view.getTag();
if (bag == null) {
bag = new BagChild();
bag.mTextName = (TextView) view.findViewById(R.id.afc_text_name);
bag.mTextPath = (TextView) view.findViewById(R.id.afc_text_path);
bag.mCheckBox = (CheckBox) view.findViewById(R.id.afc_checkbox);
view.setTag(bag);
}
/*
* Name.
*/
bag.mTextName.setText(cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_NAME)));
Ui.strikeOutText(bag.mTextName, childInfo.mMarkedAsDeleted);
/*
* Path.
*/
if (isEditor()) {
bag.mTextPath.setVisibility(View.VISIBLE);
bag.mTextPath.setText(BaseFileProviderUtils
.getRealUri(context, uri).toString());
} else
bag.mTextPath.setVisibility(View.GONE);
/*
* Checkbox.
*/
bag.mCheckBox.setVisibility(isEditor() ? View.VISIBLE : View.GONE);
bag.mCheckBox.setOnCheckedChangeListener(null);
bag.mCheckBox.setChecked(childInfo.mChecked);
bag.mCheckBox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
childInfo.mChecked = isChecked;
}// onCheckedChanged()
});
bag.mCheckBox.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ContextMenuUtils.showContextMenu(v.getContext(), 0,
R.string.afc_title_advanced_selection,
ADVANCED_SELECTION_OPTIONS,
new ContextMenuUtils.OnMenuItemClickListener() {
@Override
public void onClick(final int resId) {
if (resId == R.string.afc_cmd_advanced_selection_all)
selectAll(true);
else if (resId == R.string.afc_cmd_advanced_selection_none)
selectAll(false);
else if (resId == R.string.afc_cmd_advanced_selection_invert)
invertSelection();
}// onClick()
});
return true;
}// onLongClick()
});
}// bindChildView()
@Override
protected void bindGroupView(View view, Context context,
final Cursor cursor, boolean isExpanded) {
BagGroup b;
if (view.getTag() == null) {
b = new BagGroup();
b.mTextHeader = (TextView) view
.findViewById(R.id.afc_textview_header);
view.setTag(b);
} else
b = (BagGroup) view.getTag();
/*
* Provider name.
*/
String providerId = cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID));
b.mTextHeader.setText(BaseFileProviderUtils.getProviderName(context,
providerId));
/*
* Provider badge icon.
*/
b.mTextHeader.setCompoundDrawablesWithIntrinsicBounds(
BaseFileProviderUtils.getProviderIconId(context, providerId),
0, 0, 0);
}// bindGroupView()
@Override
public void notifyDataSetChanged(boolean releaseCursors) {
super.notifyDataSetChanged(releaseCursors);
if (releaseCursors)
synchronized (mSelectedChildrenMap) {
mSelectedChildrenMap.clear();
}
}// notifyDataSetChanged()
@Override
public void notifyDataSetInvalidated() {
super.notifyDataSetInvalidated();
synchronized (mSelectedChildrenMap) {
mSelectedChildrenMap.clear();
}
}// notifyDataSetInvalidated()
/*
* UTILITIES
*/
/**
* Checks if this is in editor mode.
*
* @return {@code true} or {@code false}.
*/
public boolean isEditor() {
return mEditor;
}// isEditor()
/**
* Sets editor mode.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param v
* {@code true} or {@code false}.
*/
public void setEditor(boolean v) {
if (mEditor != v) {
mEditor = v;
notifyDataSetChanged(false);
}
}// setEditor()
/**
* Selects all items in a specified group.
* <p/>
* <b>Note:</b> This will <i>not</i> notify data set for changes after done.
*
* @param groupPosition
* the group position.
* @param selected
* {@code true} or {@code false}.
*/
private void asyncSelectAll(int groupPosition, boolean selected) {
int chidrenCount = getChildrenCount(groupPosition);
for (int iChild = 0; iChild < chidrenCount; iChild++) {
Cursor cursor = getChild(groupPosition, iChild);
final int id = cursor.getInt(cursor
.getColumnIndex(BookmarkContract._ID));
BagChildInfo b = mSelectedChildrenMap.get(id);
if (b == null) {
b = new BagChildInfo();
mSelectedChildrenMap.put(id, b);
}
b.mChecked = selected;
}// for children
}// asyncSelectAll()
/**
* Selects all items of a specified group.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param groupPosition
* the group position.
* @param selected
* {@code true} or {@code false}.
*/
public synchronized void selectAll(int groupPosition, boolean selected) {
asyncSelectAll(groupPosition, selected);
notifyDataSetChanged(false);
}// selectAll()
/**
* Selects all items.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param selected
* {@code true} or {@code false}.
*/
public synchronized void selectAll(boolean selected) {
for (int iGroup = 0; iGroup < getGroupCount(); iGroup++)
asyncSelectAll(iGroup, selected);
notifyDataSetChanged(false);
}// selectAll()
/**
* Inverts selection.
* <p/>
* <b>Note:</b> This will <i>not</i> notify data set for changes after done.
*
* @param groupPosition
* the group position.
*/
private void asyncInvertSelection(int groupPosition) {
int chidrenCount = getChildrenCount(groupPosition);
for (int iChild = 0; iChild < chidrenCount; iChild++) {
Cursor cursor = getChild(groupPosition, iChild);
final int id = cursor.getInt(cursor
.getColumnIndex(BookmarkContract._ID));
BagChildInfo b = mSelectedChildrenMap.get(id);
if (b == null) {
b = new BagChildInfo();
mSelectedChildrenMap.put(id, b);
}
b.mChecked = !b.mChecked;
}// for children
}// asyncInvertSelection()
/**
* Inverts selection of all items of a specified group.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param groupPosition
* the group position.
*/
public synchronized void invertSelection(int groupPosition) {
asyncInvertSelection(groupPosition);
notifyDataSetChanged(false);
}// invertSelection()
/**
* Inverts selection of all items.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*/
public synchronized void invertSelection() {
for (int iGroup = 0; iGroup < getGroupCount(); iGroup++)
asyncInvertSelection(iGroup);
notifyDataSetChanged(false);
}// invertSelection()
/**
* Checks if item with {@code id} (the database ID) is selected or not.
*
* @param id
* the database ID.
* @return {@code true} or {@code false}.
*/
public boolean isSelected(int id) {
synchronized (mSelectedChildrenMap) {
return mSelectedChildrenMap.get(id) != null ? mSelectedChildrenMap
.get(id).mChecked : false;
}
}// isSelected()
/**
* Gets IDs of selected items.
*
* @return list of IDs, can be empty.
*/
public List<Integer> getSelectedItemIds() {
List<Integer> res = new ArrayList<Integer>();
synchronized (mSelectedChildrenMap) {
for (int i = 0; i < mSelectedChildrenMap.size(); i++)
if (mSelectedChildrenMap.get(mSelectedChildrenMap.keyAt(i)).mChecked)
res.add(mSelectedChildrenMap.keyAt(i));
}
return res;
}// getSelectedItemIds()
/**
* Marks all selected items as deleted.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged()} after done.
*
* @param deleted
* {@code true} or {@code false}.
*/
public void markSelectedItemsAsDeleted(boolean deleted) {
synchronized (mSelectedChildrenMap) {
for (int i = 0; i < mSelectedChildrenMap.size(); i++)
if (mSelectedChildrenMap.get(mSelectedChildrenMap.keyAt(i)).mChecked)
mSelectedChildrenMap.get(mSelectedChildrenMap.keyAt(i)).mMarkedAsDeleted = deleted;
}
notifyDataSetChanged(false);
}// markSelectedItemsAsDeleted()
/**
* Marks specified item as deleted.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged()} after done.
*
* @param id
* the database ID of the item.
* @param deleted
* {@code true} or {@code false}.
*/
public void markItemAsDeleted(int id, boolean deleted) {
synchronized (mSelectedChildrenMap) {
if (mSelectedChildrenMap.get(id) != null) {
mSelectedChildrenMap.get(id).mMarkedAsDeleted = deleted;
notifyDataSetChanged(false);
}
}
}// markItemAsDeleted()
}

View File

@ -1,804 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.utils.ui.bookmark;
import group.pals.android.lib.ui.filechooser.BuildConfig;
import group.pals.android.lib.ui.filechooser.R;
import group.pals.android.lib.ui.filechooser.prefs.DisplayPrefs;
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
import group.pals.android.lib.ui.filechooser.providers.bookmark.BookmarkContract;
import group.pals.android.lib.ui.filechooser.utils.EnvUtils;
import group.pals.android.lib.ui.filechooser.utils.TextUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.Dlg;
import group.pals.android.lib.ui.filechooser.utils.ui.GestureUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.GestureUtils.FlingDirection;
import group.pals.android.lib.ui.filechooser.utils.ui.Ui;
import group.pals.android.lib.ui.filechooser.utils.ui.history.HistoryFragment;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.TextView;
/**
* Fragment to manage bookmarks.
*
* @author Hai Bison
* @since v5.1 beta
*/
public class BookmarkFragment extends DialogFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
/**
* As the name means.
*
* @author Hai Bison
* @since v5.1 beta
*/
public static interface OnBookmarkItemClickListener {
/**
* Will be called after the bookmark was clicked.
*
* @param providerId
* the original provider ID.
* @param uri
* the URI to a directory.
*/
void onItemClick(String providerId, Uri uri);
}// OnBookmarkItemClickListener
/**
* Used for debugging or something...
*/
private static final String CLASSNAME = BookmarkFragment.class.getName();
private static final String MODE_EDITOR = CLASSNAME + ".mode_editor";
private final int mLoaderBookmarkData = EnvUtils.genId();
/**
* Creates a new instance of {@link HistoryFragment}.
*
* @param editor
* {@code true} if you want to use this as an editor, and
* {@code false} as a viewer.
* @return {@link BookmarkFragment}.
*/
public static BookmarkFragment newInstance(boolean editor) {
Bundle args = new Bundle();
args.putBoolean(MODE_EDITOR, editor);
BookmarkFragment res = new BookmarkFragment();
res.setArguments(args);
return res;
}// newInstance()
/*
* Controls.
*/
private View mViewGroupControls;
private ExpandableListView mListView;
private ViewGroup mViewFooter;
private Button mBtnClear;
private Button mBtnOk;
private View mViewLoading;
/*
* Fields.
*/
private final Handler mHandler = new Handler();
private boolean mEditor = false;
private BookmarkCursorAdapter mBookmarkCursorAdapter;
private OnBookmarkItemClickListener mOnBookmarkItemClickListener;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mEditor = getArguments().getBoolean(MODE_EDITOR);
}// onCreate()
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCreateDialog()");
Dialog dialog = new Dialog(getActivity(), Ui.resolveAttribute(
getActivity(), R.attr.afc_theme_dialog));
dialog.setCanceledOnTouchOutside(true);
dialog.requestWindowFeature(Window.FEATURE_LEFT_ICON);
dialog.setTitle(R.string.afc_title_bookmark_manager);
dialog.setContentView(initContentView(dialog.getLayoutInflater(), null));
dialog.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
R.drawable.afc_bookmarks_dark);
return dialog;
}// onCreateDialog()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCreateView()");
if (getDialog() != null) {
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode,
KeyEvent event) {
/*
* Don't let the Search key dismiss this dialog.
*/
return keyCode == KeyEvent.KEYCODE_SEARCH;
}// onKey()
});
return null;
}
return initContentView(inflater, container);
}// onCreateView()
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
/*
* Prepare the loader. Either re-connect with an existing one, or start
* a new one.
*/
getLoaderManager().initLoader(mLoaderBookmarkData, null, this);
}// onActivityCreated()
/*
* LOADERMANAGER.LOADERCALLBACKS
*/
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCreateLoader()");
if (id == mLoaderBookmarkData) {
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(mViewLoadingShower,
DisplayPrefs.DELAY_TIME_FOR_SIMPLE_ANIMATION);
mBookmarkCursorAdapter.changeCursor(null);
return new CursorLoader(getActivity(),
BookmarkContract.genContentUri(getActivity()), null, null,
null, String.format("%s, %s DESC",
BookmarkContract.COLUMN_PROVIDER_ID,
BookmarkContract.COLUMN_MODIFICATION_TIME));
}// mLoaderBookmarkData
return null;
}// onCreateLoader()
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onLoadFinished() -- data = " + data);
if (loader.getId() == mLoaderBookmarkData) {
mBookmarkCursorAdapter.changeCursor(data);
for (int i = 0; i < mBookmarkCursorAdapter.getGroupCount(); i++)
mListView.expandGroup(i);
updateUI();
/*
* Views visibilities. Always call these to make sure all views are
* in right visibilities.
*/
mHandler.removeCallbacksAndMessages(null);
mViewLoading.setVisibility(View.GONE);
mViewGroupControls.setVisibility(View.VISIBLE);
mListView.post(new Runnable() {
@Override
public void run() {
mListView.setSelection(-1);
}
});
}// mLoaderBookmarkData
}// onLoadFinished()
@Override
public void onLoaderReset(Loader<Cursor> loader) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onLoaderReset()");
if (loader.getId() == mLoaderBookmarkData) {
mBookmarkCursorAdapter.changeCursor(null);
mViewLoading.setVisibility(View.VISIBLE);
}// mLoaderBookmarkData
}// onLoaderReset()
/**
* Loads content view from XML and init controls.
*/
private View initContentView(LayoutInflater inflater, ViewGroup container) {
View mainView = inflater.inflate(R.layout.afc_viewgroup_bookmarks,
container, false);
/*
* Maps controls.
*/
mViewGroupControls = mainView.findViewById(R.id.afc_viewgroup_controls);
mListView = (ExpandableListView) mainView
.findViewById(R.id.afc_listview_bookmarks);
mViewFooter = (ViewGroup) mainView
.findViewById(R.id.afc_viewgroup_footer);
mBtnClear = (Button) mainView.findViewById(R.id.afc_button_clear);
mBtnOk = (Button) mainView.findViewById(R.id.afc_button_ok);
mViewLoading = mainView.findViewById(R.id.afc_view_loading);
if (mEditor) {
mViewFooter.setVisibility(View.VISIBLE);
}
/*
* Listview.
*/
mListView.setEmptyView(mainView.findViewById(R.id.afc_empty_view));
mListView.setOnChildClickListener(mListViewOnChildClickListener);
mListView.setOnItemLongClickListener(mListViewOnItemLongClickListener);
initListViewGestureListener();
/*
* Adapter.
*/
mBookmarkCursorAdapter = new BookmarkCursorAdapter(getActivity());
mBookmarkCursorAdapter.setEditor(mEditor);
mListView.setAdapter(mBookmarkCursorAdapter);
/*
* Events.
*/
mBtnClear.setOnClickListener(mBtnClearOnClickListener);
mBtnOk.setOnClickListener(mBtnOkOnClickListener);
return mainView;
}// initContentView()
/**
* As the name means.
*/
private void initListViewGestureListener() {
GestureUtils.setupGestureDetector(mListView,
new GestureUtils.SimpleOnGestureListener() {
@Override
public boolean onFling(View view, Object data,
FlingDirection flingDirection) {
if (!isEditor() || !(data instanceof Cursor))
return false;
List<Integer> ids = new ArrayList<Integer>();
final int bookmarkId = ((Cursor) data)
.getInt(((Cursor) data)
.getColumnIndex(BookmarkContract._ID));
if (mBookmarkCursorAdapter.isSelected(bookmarkId))
ids.addAll(mBookmarkCursorAdapter
.getSelectedItemIds());
else
ids.add(bookmarkId);
if (ids.size() <= 1)
mBookmarkCursorAdapter.markItemAsDeleted(
bookmarkId, true);
else
mBookmarkCursorAdapter
.markSelectedItemsAsDeleted(true);
final StringBuilder sb = new StringBuilder(String
.format("%s in (",
DbUtils.SQLITE_FTS_COLUMN_ROW_ID));
for (int id : ids)
sb.append(Integer.toString(id)).append(',');
sb.setCharAt(sb.length() - 1, ')');
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
getActivity().getContentResolver().delete(
BookmarkContract
.genContentUri(getActivity()),
sb.toString(), null);
}// run()
}, DisplayPrefs.DELAY_TIME_FOR_VERY_SHORT_ANIMATION);
return true;
}// onFling()
});
}// initListViewGestureListener()
/**
* Updates UI.
*/
private void updateUI() {
mViewFooter.setVisibility(isEditor() ? View.VISIBLE : View.GONE);
mBtnClear.setEnabled(mBookmarkCursorAdapter.getGroupCount() > 0);
}// updateUI()
/*
* UTILITIES
*/
/**
* Enables or disables editor mode.
*
* @param editor
* {@code true} to enable, {@code false} to disable.
*/
public void setEditor(boolean editor) {
if (mEditor != editor) {
mEditor = editor;
if (mBookmarkCursorAdapter != null)
mBookmarkCursorAdapter.setEditor(mEditor);
updateUI();
}
}// setEditor()
/**
* Checks if current mode is editor or not.
*
* @return {@code true} if current mode is editor.
*/
public boolean isEditor() {
return mEditor;
}// isEditor()
/**
* Sets a listener to {@link OnBookmarkItemClickListener}.
*
* @param listener
* the listener.
*/
public void setOnBookmarkItemClickListener(
OnBookmarkItemClickListener listener) {
mOnBookmarkItemClickListener = listener;
}// setOnBookmarkItemClickListener()
/**
* Gets the listener of {@link OnBookmarkItemClickListener}.
*
* @return the listener.
*/
public OnBookmarkItemClickListener getOnBookmarkItemClickListener() {
return mOnBookmarkItemClickListener;
}// getOnBookmarkItemClickListener()
/*
* LISTENERS
*/
private final Runnable mViewLoadingShower = new Runnable() {
@Override
public void run() {
if (isAdded()) {
mViewGroupControls.setVisibility(View.GONE);
mViewLoading.setVisibility(View.VISIBLE);
}
}// run()
};// mViewLoadingShower
private final ExpandableListView.OnChildClickListener mListViewOnChildClickListener = new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
if (getOnBookmarkItemClickListener() != null) {
Cursor cursor = mBookmarkCursorAdapter.getChild(groupPosition,
childPosition);
getOnBookmarkItemClickListener()
.onItemClick(
cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID)),
Uri.parse(cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_URI))));
}
if (getDialog() != null)
dismiss();
return false;
}// onChildClick()
};// mListViewOnChildClickListener
private final AdapterView.OnItemLongClickListener mListViewOnItemLongClickListener = new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
final int iGroup = ExpandableListView
.getPackedPositionGroup(mListView
.getExpandableListPosition(position));
final int iChild = ExpandableListView
.getPackedPositionChild(mListView
.getExpandableListPosition(position));
switch (ExpandableListView.getPackedPositionType(id)) {
case ExpandableListView.PACKED_POSITION_TYPE_GROUP:
if (!isEditor())
return false;
if (!mListView.isGroupExpanded(iGroup))
return false;
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, String.format(
"onItemLongClick() -- group = %,d", iGroup));
ContextMenuUtils.showContextMenu(getActivity(), 0,
R.string.afc_title_advanced_selection,
BookmarkCursorAdapter.ADVANCED_SELECTION_OPTIONS,
new ContextMenuUtils.OnMenuItemClickListener() {
@Override
public void onClick(final int resId) {
if (resId == R.string.afc_cmd_advanced_selection_all)
mBookmarkCursorAdapter.selectAll(iGroup,
true);
else if (resId == R.string.afc_cmd_advanced_selection_none)
mBookmarkCursorAdapter.selectAll(iGroup,
false);
else if (resId == R.string.afc_cmd_advanced_selection_invert)
mBookmarkCursorAdapter
.invertSelection(iGroup);
}// onClick()
});
return true;// PACKED_POSITION_TYPE_GROUP
case ExpandableListView.PACKED_POSITION_TYPE_CHILD:
Cursor cursor = mBookmarkCursorAdapter.getChild(iGroup, iChild);
final String providerId = cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_PROVIDER_ID));
final int bookmarkId = cursor.getInt(cursor
.getColumnIndex(BookmarkContract._ID));
final Uri uri = Uri.parse(cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_URI)));
final String name = cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_NAME));
ContextMenuUtils.showContextMenu(getActivity(),
R.drawable.afc_bookmarks_dark, TextUtils.quote(name),
new Integer[] { R.string.afc_cmd_rename,
R.string.afc_cmd_sort_by_name },
new ContextMenuUtils.OnMenuItemClickListener() {
@Override
public void onClick(int resId) {
if (resId == R.string.afc_cmd_rename) {
doEnterNewNameOrRenameBookmark(
getActivity(), providerId,
bookmarkId, uri, name);
} else if (resId == R.string.afc_cmd_sort_by_name) {
sortBookmarks(iGroup);
}
}// onClick()
});
return true;// PACKED_POSITION_TYPE_CHILD
}
return false;
}// onItemLongClick()
/**
* Sorts bookmarks.
*
* @param groupPosition
* the group position.
*/
private void sortBookmarks(int groupPosition) {
SparseArray<String> bookmarks = new SparseArray<String>();
List<String> names = new ArrayList<String>();
for (int i = 0; i < mBookmarkCursorAdapter
.getChildrenCount(groupPosition); i++) {
Cursor cursor = mBookmarkCursorAdapter.getChild(groupPosition,
i);
names.add(cursor.getString(cursor
.getColumnIndex(BookmarkContract.COLUMN_NAME)));
bookmarks.put(cursor.getInt(cursor
.getColumnIndex(BookmarkContract._ID)), names.get(i));
}
Collections.sort(names, new Comparator<String>() {
final Collator mCollator = Collator.getInstance();
@Override
public int compare(String lhs, String rhs) {
return mCollator.compare(lhs, rhs);
}// compare()
});
ContentResolver contentResolver = getActivity()
.getContentResolver();
/*
* The list was sorted ascending by name (A-Z), now we add "i" to
* timestamp (last modified), so the list will be obtained ascending
* by name (A-Z) as it will be obtained from DB descending by last
* modified.
*/
ContentValues values = new ContentValues();
while (names.size() > 0) {
values.put(
BookmarkContract.COLUMN_MODIFICATION_TIME,
DbUtils.formatNumber(new Date().getTime()
+ bookmarks.size() - names.size()));
contentResolver.update(BookmarkContract
.genContentUri(getActivity()), values, String.format(
"%s = %d", DbUtils.SQLITE_FTS_COLUMN_ROW_ID, bookmarks
.keyAt(bookmarks.indexOfValue(names
.remove(names.size() - 1)))), null);
}
}// sortBookmarks()
};// mListViewOnItemLongClickListener
/**
* Shows a dialog to let the user enter new name or change current name of a
* bookmark.
*
* @param context
* {@link Context}
* @param providerId
* the provider ID.
* @param id
* the bookmark ID.
* @param uri
* the URI to the bookmark.
* @param name
* the name. To enter new name, this is the suggested name you
* provide. To rename, this is the old name.
*/
public static void doEnterNewNameOrRenameBookmark(final Context context,
final String providerId, final int id, final Uri uri,
final String name) {
final AlertDialog dialog = Dlg.newAlertDlg(context);
View view = LayoutInflater.from(context).inflate(
R.layout.afc_simple_text_input_view, null);
final EditText textName = (EditText) view.findViewById(R.id.afc_text1);
textName.setText(name);
textName.selectAll();
textName.setHint(R.string.afc_hint_new_name);
textName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
Ui.showSoftKeyboard(textName, false);
Button btn = dialog
.getButton(DialogInterface.BUTTON_POSITIVE);
if (btn.isEnabled())
btn.performClick();
return true;
}
return false;
}// onEditorAction()
});
dialog.setView(view);
dialog.setIcon(R.drawable.afc_bookmarks_dark);
dialog.setTitle(id < 0 ? R.string.afc_title_new_bookmark
: R.string.afc_title_rename);
dialog.setButton(DialogInterface.BUTTON_POSITIVE,
context.getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String newName = textName.getText().toString().trim();
if (android.text.TextUtils.isEmpty(newName)) {
Dlg.toast(context,
R.string.afc_msg_bookmark_name_is_invalid,
Dlg.LENGTH_SHORT);
return;
}
Ui.showSoftKeyboard(textName, false);
ContentValues values = new ContentValues();
values.put(BookmarkContract.COLUMN_NAME, newName);
if (id >= 0) {
values.put(
BookmarkContract.COLUMN_MODIFICATION_TIME,
DbUtils.formatNumber(new Date().getTime()));
context.getContentResolver().update(
Uri.withAppendedPath(BookmarkContract
.genContentIdUriBase(context), Uri
.encode(Integer.toString(id))),
values, null, null);
} else {
/*
* Check if the URI exists or doesn't. If it exists,
* update it instead of inserting the new one.
*/
Cursor cursor = context
.getContentResolver()
.query(BookmarkContract
.genContentUri(context),
null,
String.format(
"%s = %s AND %s LIKE %s",
BookmarkContract.COLUMN_PROVIDER_ID,
DatabaseUtils
.sqlEscapeString(providerId),
BookmarkContract.COLUMN_URI,
DatabaseUtils
.sqlEscapeString(uri
.toString())),
null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
values.put(
BookmarkContract.COLUMN_MODIFICATION_TIME,
DbUtils.formatNumber(new Date()
.getTime()));
context.getContentResolver()
.update(Uri
.withAppendedPath(
BookmarkContract
.genContentIdUriBase(context),
Uri.encode(cursor
.getString(cursor
.getColumnIndex(BookmarkContract._ID)))),
values, null, null);
} else {
values.put(
BookmarkContract.COLUMN_PROVIDER_ID,
providerId);
values.put(BookmarkContract.COLUMN_URI,
uri.toString());
context.getContentResolver().insert(
BookmarkContract
.genContentUri(context),
values);
}
} finally {
if (cursor != null)
cursor.close();
}
}
Dlg.toast(context,
context.getString(R.string.afc_msg_done),
Dlg.LENGTH_SHORT);
}// onClick()
});
dialog.show();
Ui.showSoftKeyboard(textName, true);
final Button buttonOk = dialog
.getButton(DialogInterface.BUTTON_POSITIVE);
buttonOk.setEnabled(id < 0);
textName.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
String newName = s.toString().trim();
boolean enabled = !android.text.TextUtils.isEmpty(newName);
buttonOk.setEnabled(enabled);
/*
* If renaming, only enable button OK if new name is not equal
* to the old one.
*/
if (enabled && id >= 0)
buttonOk.setEnabled(!newName.equals(name));
}
});
}// doEnterNewNameOrRenameBookmark()
private final View.OnClickListener mBtnClearOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mBookmarkCursorAdapter.getGroupCount() == 1
&& mBookmarkCursorAdapter.getChildrenCount(0) == 1) {
clearBookmarksAndDismiss();
} else {
Dlg.confirmYesno(
getActivity(),
getString(R.string.afc_msg_confirm_clear_all_bookmarks),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
clearBookmarksAndDismiss();
}// onClick()
});
}
}// onClick()
private void clearBookmarksAndDismiss() {
getActivity().getContentResolver().delete(
BookmarkContract.genContentUri(getActivity()), null, null);
updateUI();
if (getDialog() != null)
dismiss();
}// clearBookmarks()
};// mBtnClearOnClickListener
private final View.OnClickListener mBtnOkOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getDialog() != null)
dismiss();
else
setEditor(false);
}// onClick()
};// mBtnOkOnClickListener
}

View File

@ -1,613 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.utils.ui.history;
import group.pals.android.lib.ui.filechooser.BuildConfig;
import group.pals.android.lib.ui.filechooser.R;
import group.pals.android.lib.ui.filechooser.providers.BaseFileProviderUtils;
import group.pals.android.lib.ui.filechooser.providers.basefile.BaseFileContract.BaseFile;
import group.pals.android.lib.ui.filechooser.providers.history.HistoryContract;
import group.pals.android.lib.ui.filechooser.utils.DateUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.Ui;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.util.Log;
import android.util.SparseArray;
import android.view.View;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ResourceCursorTreeAdapter;
import android.widget.TextView;
/**
* History cursor adapter.
*
* @author Hai Bison
* @since v5.1 beta
*/
public class HistoryCursorAdapter extends ResourceCursorTreeAdapter {
private static final String CLASSNAME = HistoryCursorAdapter.class
.getName();
/**
* @see android.text.format.DateUtils#DAY_IN_MILLIS
*/
private static final long DAY_IN_MILLIS = android.text.format.DateUtils.DAY_IN_MILLIS;
/**
* Advanced selection options: All, None, Invert.
*/
public static final Integer[] ADVANCED_SELECTION_OPTIONS = new Integer[] {
R.string.afc_cmd_advanced_selection_all,
R.string.afc_cmd_advanced_selection_none,
R.string.afc_cmd_advanced_selection_invert };
private static class BagGroup {
TextView mTextViewHeader;
}// BagGroup
private static class BagChild {
TextView mTextViewTime;
TextView mTextViewName;
TextView mTextViewPath;
CheckBox mCheckBox;
}// BagChild
private static class BagChildInfo {
boolean mChecked = false;
boolean mMarkedAsDeleted = false;
}// BagChildInfo
/**
* This column holds the original position of group cursor in original
* cursor.
* <p/>
* Type: {@code Integer}
*/
private static final String COLUMN_ORG_GROUP_POSITION = "org_group_position";
private static final String[] GROUP_CURSOR_COLUMNS = { HistoryContract._ID,
HistoryContract.COLUMN_MODIFICATION_TIME, COLUMN_ORG_GROUP_POSITION };
private static final String[] CHILD_CURSOR_COLUMNS = { HistoryContract._ID,
HistoryContract.COLUMN_URI, HistoryContract.COLUMN_PROVIDER_ID,
HistoryContract.COLUMN_MODIFICATION_TIME, BaseFile.COLUMN_NAME,
BaseFile.COLUMN_REAL_URI };
/**
* Map of child IDs to {@link BagChildInfo}.
*/
private final SparseArray<BagChildInfo> mSelectedChildrenMap = new SparseArray<BagChildInfo>();
private Cursor mOrgCursor;
private MatrixCursor mGroupCursor;
private SparseArray<MatrixCursor> mChildrenCursor;
private CharSequence mSearchText;
/**
* Creates new instance.
*
* @param context
* {@link Context}.
*/
public HistoryCursorAdapter(Context context) {
super(context, null, R.layout.afc_view_history_item,
R.layout.afc_view_history_sub_item);
}// BookmarkCursorAdapter()
/**
* Changes new cursor.
* <p/>
* You have to query the items in descending order of modification time.
*
* @param cursor
* the cursor.
* @param notificationUri
* the notification URI.
*/
@Override
public synchronized void changeCursor(Cursor cursor) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "changeCursor()");
if (mOrgCursor != null)
mOrgCursor.close();
mOrgCursor = cursor;
MatrixCursor newGroupCursor = cursor != null ? new MatrixCursor(
GROUP_CURSOR_COLUMNS) : null;
SparseArray<MatrixCursor> newChildrenCursor = cursor != null ? new SparseArray<MatrixCursor>()
: null;
/*
* Build new group cursor.
*/
if (cursor != null && cursor.moveToFirst()) {
long lastDayCount = 0;
do {
long dayCount = (long) Math
.floor((Long.parseLong(cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME))) + TimeZone
.getDefault().getRawOffset())
/ DAY_IN_MILLIS);
if (dayCount != lastDayCount || newGroupCursor.getCount() == 0) {
newGroupCursor
.addRow(new Object[] {
cursor.getInt(cursor
.getColumnIndex(HistoryContract._ID)),
cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME)),
cursor.getPosition() });
}
lastDayCount = dayCount;
} while (cursor.moveToNext());
}
/*
* Clean up children cursor.
*/
if (mChildrenCursor != null) {
for (int i = 0; i < mChildrenCursor.size(); i++)
mChildrenCursor.valueAt(i).close();
mChildrenCursor.clear();
}
/*
* Apply new changes... Note that we don't need to close the old group
* cursor. The call to `super.changeCursor()` will do that.
*/
mGroupCursor = newGroupCursor;
mChildrenCursor = newChildrenCursor;
super.changeCursor(mGroupCursor);
}// changeCursor()
@Override
protected Cursor getChildrenCursor(Cursor groupCursor) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "getChildrenCursor()");
/*
* Try to find the child cursor in the map. If found then it'd be great
* :-)
*/
int orgGroupPosition = groupCursor.getInt(groupCursor
.getColumnIndex(COLUMN_ORG_GROUP_POSITION));
int idx = mChildrenCursor.indexOfKey(orgGroupPosition);
if (idx >= 0)
return mChildrenCursor.valueAt(idx);
/*
* If not found, create new cursor.
*/
MatrixCursor childrenCursor = new MatrixCursor(CHILD_CURSOR_COLUMNS);
mOrgCursor.moveToPosition(orgGroupPosition);
long startOfDay = Long.parseLong(groupCursor.getString(groupCursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME)))
+ TimeZone.getDefault().getRawOffset();
startOfDay -= startOfDay % DAY_IN_MILLIS;
do {
childrenCursor
.addRow(new Object[] {
mOrgCursor.getInt(mOrgCursor
.getColumnIndex(HistoryContract._ID)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(HistoryContract.COLUMN_URI)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(HistoryContract.COLUMN_PROVIDER_ID)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(BaseFile.COLUMN_NAME)),
mOrgCursor.getString(mOrgCursor
.getColumnIndex(BaseFile.COLUMN_REAL_URI)) });
} while (mOrgCursor.moveToNext()
&& Long.parseLong(mOrgCursor.getString(mOrgCursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME)))
+ TimeZone.getDefault().getRawOffset() >= startOfDay);
/*
* Put it to the map.
*/
mChildrenCursor.put(orgGroupPosition, childrenCursor);
return childrenCursor;
}// getChildrenCursor()
@Override
protected void bindChildView(View view, Context context, Cursor cursor,
boolean isLastChild) {
final int id = cursor
.getInt(cursor.getColumnIndex(HistoryContract._ID));
final BagChild child;
if (view.getTag() == null) {
child = new BagChild();
child.mTextViewTime = (TextView) view
.findViewById(R.id.afc_textview_time);
child.mTextViewName = (TextView) view
.findViewById(R.id.afc_textview_name);
child.mTextViewPath = (TextView) view
.findViewById(R.id.afc_textview_path);
child.mCheckBox = (CheckBox) view.findViewById(R.id.afc_checkbox);
view.setTag(child);
} else
child = (BagChild) view.getTag();
final BagChildInfo childInfo;
if (mSelectedChildrenMap.get(id) == null) {
childInfo = new BagChildInfo();
mSelectedChildrenMap.put(id, childInfo);
} else
childInfo = mSelectedChildrenMap.get(id);
String fileName = null;
String fileUri = null;
int col = -1;
if ((col = cursor.getColumnIndex(BaseFile.COLUMN_NAME)) >= 0)
fileName = cursor.getString(col);
if ((col = cursor.getColumnIndex(BaseFile.COLUMN_REAL_URI)) >= 0)
fileUri = cursor.getString(col);
child.mTextViewTime
.setText(formatTime(
view.getContext(),
Long.parseLong(cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME)))));
child.mTextViewName.setText(fileName);
Ui.strikeOutText(child.mTextViewName, childInfo.mMarkedAsDeleted);
child.mTextViewPath.setText(fileUri);
/*
* Provider ID.
*/
String providerId = cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_PROVIDER_ID));
/*
* Provider badge icon.
*/
child.mTextViewTime.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0,
BaseFileProviderUtils.getProviderIconId(context, providerId));
/*
* Check box.
*/
child.mCheckBox.setOnCheckedChangeListener(null);
child.mCheckBox.setChecked(childInfo.mChecked);
child.mCheckBox
.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCheckedChanged() >> id = " + id);
childInfo.mChecked = isChecked;
}// onCheckedChanged()
});
child.mCheckBox.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ContextMenuUtils.showContextMenu(v.getContext(), 0,
R.string.afc_title_advanced_selection,
ADVANCED_SELECTION_OPTIONS,
new ContextMenuUtils.OnMenuItemClickListener() {
@Override
public void onClick(final int resId) {
if (resId == R.string.afc_cmd_advanced_selection_all)
selectAll(true);
else if (resId == R.string.afc_cmd_advanced_selection_none)
selectAll(false);
else if (resId == R.string.afc_cmd_advanced_selection_invert)
invertSelection();
}// onClick()
});
return true;
}// onLongClick()
});
}// bindChildView()
@Override
protected void bindGroupView(View view, Context context,
final Cursor cursor, boolean isExpanded) {
BagGroup b;
if (view.getTag() == null) {
b = new BagGroup();
b.mTextViewHeader = (TextView) view
.findViewById(R.id.afc_textview_header);
view.setTag(b);
} else
b = (BagGroup) view.getTag();
b.mTextViewHeader
.setText(formatDate(
view.getContext(),
Long.parseLong(cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_MODIFICATION_TIME)))));
}// bindGroupView()
@Override
public void notifyDataSetChanged(boolean releaseCursors) {
super.notifyDataSetChanged(releaseCursors);
if (releaseCursors)
synchronized (mSelectedChildrenMap) {
mSelectedChildrenMap.clear();
}
}// notifyDataSetChanged()
@Override
public void notifyDataSetInvalidated() {
super.notifyDataSetInvalidated();
synchronized (mSelectedChildrenMap) {
mSelectedChildrenMap.clear();
}
}// notifyDataSetInvalidated()
/*
* UTILITIES
*/
/**
* Gets the search text.
*
* @return the search text, can be {@code null}.
*/
public CharSequence getSearchText() {
return mSearchText;
}// getSearchText()
/**
* Sets search text.
*
* @param searchText
* the search text.
*/
public void setSearchText(CharSequence searchText) {
mSearchText = searchText;
}// setSearchText()
/**
* Selects all items in a specified group.
* <p/>
* <b>Note:</b> This will <i>not</i> notify data set for changes after done.
*
* @param groupPosition
* the group position.
* @param selected
* {@code true} or {@code false}.
*/
private void asyncSelectAll(int groupPosition, boolean selected) {
int chidrenCount = getChildrenCount(groupPosition);
for (int iChild = 0; iChild < chidrenCount; iChild++) {
Cursor cursor = getChild(groupPosition, iChild);
final int id = cursor.getInt(cursor
.getColumnIndex(HistoryContract._ID));
BagChildInfo childInfo = mSelectedChildrenMap.get(id);
if (childInfo == null) {
childInfo = new BagChildInfo();
mSelectedChildrenMap.put(id, childInfo);
}
childInfo.mChecked = selected;
}// for children
}// asyncSelectAll()
/**
* Selects all items of a specified group.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param groupPosition
* the group position.
* @param selected
* {@code true} or {@code false}.
*/
public synchronized void selectAll(int groupPosition, boolean selected) {
asyncSelectAll(groupPosition, selected);
notifyDataSetChanged(false);
}// selectAll()
/**
* Selects all items.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param selected
* {@code true} or {@code false}.
*/
public synchronized void selectAll(boolean selected) {
for (int iGroup = 0; iGroup < getGroupCount(); iGroup++)
asyncSelectAll(iGroup, selected);
notifyDataSetChanged(false);
}// selectAll()
/**
* Inverts selection.
* <p/>
* <b>Note:</b> This will <i>not</i> notify data set for changes after done.
*
* @param groupPosition
* the group position.
*/
private void asyncInvertSelection(int groupPosition) {
int chidrenCount = getChildrenCount(groupPosition);
for (int iChild = 0; iChild < chidrenCount; iChild++) {
Cursor cursor = getChild(groupPosition, iChild);
final int id = cursor.getInt(cursor
.getColumnIndex(HistoryContract._ID));
BagChildInfo childInfo = mSelectedChildrenMap.get(id);
if (childInfo == null) {
childInfo = new BagChildInfo();
mSelectedChildrenMap.put(id, childInfo);
}
childInfo.mChecked = !childInfo.mChecked;
}// for children
}// asyncInvertSelection()
/**
* Inverts selection of all items of a specified group.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*
* @param groupPosition
* the group position.
*/
public synchronized void invertSelection(int groupPosition) {
asyncInvertSelection(groupPosition);
notifyDataSetChanged(false);
}// invertSelection()
/**
* Inverts selection of all items.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged(boolean)} (with
* {@code false}) after done.
*/
public synchronized void invertSelection() {
for (int iGroup = 0; iGroup < getGroupCount(); iGroup++)
asyncInvertSelection(iGroup);
notifyDataSetChanged(false);
}// invertSelection()
/**
* Checks if item with {@code id} (the database ID) is selected or not.
*
* @param id
* the database ID.
* @return {@code true} or {@code false}.
*/
public boolean isSelected(int id) {
synchronized (mSelectedChildrenMap) {
return mSelectedChildrenMap.get(id) != null ? mSelectedChildrenMap
.get(id).mChecked : false;
}
}// isSelected()
/**
* Gets IDs of selected items.
*
* @return list of IDs, can be empty.
*/
public List<Integer> getSelectedItemIds() {
List<Integer> res = new ArrayList<Integer>();
synchronized (mSelectedChildrenMap) {
for (int i = 0; i < mSelectedChildrenMap.size(); i++)
if (mSelectedChildrenMap.get(mSelectedChildrenMap.keyAt(i)).mChecked)
res.add(mSelectedChildrenMap.keyAt(i));
}
return res;
}// getSelectedItemIds()
/**
* Marks all selected items as deleted.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged()} after done.
*
* @param deleted
* {@code true} or {@code false}.
*/
public void markSelectedItemsAsDeleted(boolean deleted) {
synchronized (mSelectedChildrenMap) {
for (int i = 0; i < mSelectedChildrenMap.size(); i++)
if (mSelectedChildrenMap.get(mSelectedChildrenMap.keyAt(i)).mChecked)
mSelectedChildrenMap.get(mSelectedChildrenMap.keyAt(i)).mMarkedAsDeleted = deleted;
}
notifyDataSetChanged(false);
}// markSelectedItemsAsDeleted()
/**
* Marks specified item as deleted.
* <p/>
* <b>Note:</b> This calls {@link #notifyDataSetChanged()} after done.
*
* @param id
* the database ID of the item.
* @param deleted
* {@code true} or {@code false}.
*/
public void markItemAsDeleted(int id, boolean deleted) {
synchronized (mSelectedChildrenMap) {
if (mSelectedChildrenMap.get(id) != null) {
mSelectedChildrenMap.get(id).mMarkedAsDeleted = deleted;
notifyDataSetChanged(false);
}
}
}// markItemAsDeleted()
/*
* STATIC UTILITIES
*/
/**
* Formats {@code millis} to time.
*
* @param c
* {@link Context}.
* @param millis
* the time in milliseconds.
* @return the formatted time.
*/
private static String formatDate(Context c, long millis) {
if (android.text.format.DateUtils.isToday(millis))
return c.getString(R.string.afc_today);
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(millis);
final Calendar yesterday = Calendar.getInstance();
yesterday.add(Calendar.DAY_OF_YEAR, -1);
if (cal.get(Calendar.YEAR) == yesterday.get(Calendar.YEAR)) {
if (cal.get(Calendar.DAY_OF_YEAR) == yesterday
.get(Calendar.DAY_OF_YEAR))
return c.getString(R.string.afc_yesterday);
else
return android.text.format.DateUtils.formatDateTime(c, millis,
DateUtils.FORMAT_MONTH_AND_DAY);
}
return android.text.format.DateUtils.formatDateTime(c, millis,
DateUtils.FORMAT_MONTH_AND_DAY | DateUtils.FORMAT_YEAR);
}// formatDate()
/**
* Formats {@code millis} to short time. E.g: "10:01am".
*
* @param c
* {@link Context}.
* @param millis
* time in milliseconds.
* @return the formatted time.
*/
private static String formatTime(Context c, long millis) {
return android.text.format.DateUtils.formatDateTime(c, millis,
DateUtils.FORMAT_SHORT_TIME);
}// formatTime()
}

View File

@ -1,774 +0,0 @@
/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.utils.ui.history;
import group.pals.android.lib.ui.filechooser.BuildConfig;
import group.pals.android.lib.ui.filechooser.R;
import group.pals.android.lib.ui.filechooser.prefs.DisplayPrefs;
import group.pals.android.lib.ui.filechooser.providers.DbUtils;
import group.pals.android.lib.ui.filechooser.providers.history.HistoryContract;
import group.pals.android.lib.ui.filechooser.ui.widget.AfcSearchView;
import group.pals.android.lib.ui.filechooser.utils.EnvUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.Dlg;
import group.pals.android.lib.ui.filechooser.utils.ui.GestureUtils;
import group.pals.android.lib.ui.filechooser.utils.ui.GestureUtils.FlingDirection;
import group.pals.android.lib.ui.filechooser.utils.ui.Ui;
import java.util.ArrayList;
import java.util.List;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ExpandableListView;
/**
* Fragment used to manage history.
*
* @author Hai Bison
* @since v5.1 beta
*/
public class HistoryFragment extends DialogFragment implements
LoaderManager.LoaderCallbacks<Cursor> {
/**
* Used for debugging or something...
*/
private static final String CLASSNAME = HistoryFragment.class.getName();
/**
* As the name means.
*
* @author Hai Bison
* @since v5.1 beta
*/
public static interface OnHistoryItemClickListener {
/**
* Will be called after history item was clicked.
*
* @param providerId
* the original provider ID.
* @param uri
* the URI to a directory or a file.
*/
void onItemClick(String providerId, Uri uri);
}// OnHistoryItemClickListener
/**
* Creates a new instance of {@link HistoryFragment}.
*/
public static HistoryFragment newInstance() {
return new HistoryFragment();
}// newInstance()
private final int mLoaderIdHistoryData = EnvUtils.genId();
private final int mLoaderIdHistoryCounter = EnvUtils.genId();
/*
* Fields.
*/
private OnHistoryItemClickListener mOnHistoryItemClickListener;
private final Handler mHandler = new Handler();
private int mLastScreenOrientation;
private int mMaxItemsPerPage;
private int mItemCount = 0;
private int mPageCount = 1;
private int mCurrentPage = 0;
private Cursor mCursorCounter;
/*
* Controls.
*/
private View mBtnSearch;
private View mViewGroupListView;
private ExpandableListView mListView;
private HistoryCursorAdapter mHistoryCursorAdapter;
private AfcSearchView mSearchView;
private View mBtnNext;
private View mBtnPrev;
private View mViewLoading;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMaxItemsPerPage = getResources().getInteger(
R.integer.afc_pkey_history_manager_display_items_per_page);
}// onCreate()
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCreateDialog()");
Dialog dialog = new Dialog(getActivity(), Ui.resolveAttribute(
getActivity(), R.attr.afc_theme_dialog)) {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getActivity().getMenuInflater().inflate(
R.menu.afc_viewgroup_history, menu);
return super.onCreateOptionsMenu(menu);
}// onCreateOptionsMenu()
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.afc_menuitem_clear).setEnabled(
mHistoryCursorAdapter != null
&& mHistoryCursorAdapter.getGroupCount() > 0);
return true;
}// onPrepareOptionsMenu()
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onMenuItemSelected() in Dialog");
Ui.showSoftKeyboard(mSearchView, false);
if (item.getItemId() == R.id.afc_menuitem_clear)
doConfirmClearHistory();
return true;
}// onMenuItemSelected()
};
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCanceledOnTouchOutside(true);
dialog.setContentView(initContentView(dialog.getLayoutInflater(), null));
dialog.setOnKeyListener(mDialogOnKeyListener);
Ui.adjustDialogSizeForLargeScreen(dialog);
return dialog;
}// onCreateDialog()
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCreateView() -- getDialog() = " + getDialog());
return getDialog() != null ? null
: initContentView(inflater, container);
}// onCreateView()
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
/*
* Prepare the loaders. Either re-connect with the existing ones, or
* start the new ones.
*/
getLoaderManager().initLoader(mLoaderIdHistoryCounter, null, this);
getLoaderManager().initLoader(mLoaderIdHistoryData, null, this);
}// onActivityCreated()
@Override
public void onResume() {
super.onResume();
if (mLastScreenOrientation != getResources().getConfiguration().orientation) {
mLastScreenOrientation = getResources().getConfiguration().orientation;
Ui.adjustDialogSizeForLargeScreen(getDialog());
}
}// onResume()
@Override
public void onPause() {
super.onPause();
mLastScreenOrientation = getResources().getConfiguration().orientation;
}// onPause()
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (getDialog() != null)
Ui.adjustDialogSizeForLargeScreen(getDialog());
}// onConfigurationChanged()
/*
* LOADERMANAGER.LOADERCALLBACKS
*/
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onCreateLoader()");
enableControls(false);
String selection = null;
if (!TextUtils.isEmpty(mHistoryCursorAdapter.getSearchText())) {
selection = DbUtils.rawSqlEscapeString(Uri
.encode(mHistoryCursorAdapter.getSearchText().toString()));
selection = String.format("%s LIKE '%%://%%%s%%'",
HistoryContract.COLUMN_URI, selection);
}
if (id == mLoaderIdHistoryData) {
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(mViewLoadingShower,
DisplayPrefs.DELAY_TIME_FOR_SIMPLE_ANIMATION);
mHistoryCursorAdapter.changeCursor(null);
/*
* Offset.
*/
if (mCurrentPage >= mPageCount)
mCurrentPage = mPageCount - 1;
if (mCurrentPage < 0)
mCurrentPage = 0;
int offset = mCurrentPage * mMaxItemsPerPage;
return new CursorLoader(getActivity(),
HistoryContract.genContentUri(getActivity()), null,
selection, null, String.format(
"%s DESC LIMIT %s OFFSET %s",
HistoryContract.COLUMN_MODIFICATION_TIME,
mMaxItemsPerPage, offset));
} // mLoaderIdHistoryData
else if (id == mLoaderIdHistoryCounter) {
mPageCount = 1;
mCurrentPage = 0;
if (mCursorCounter != null) {
mCursorCounter.close();
mCursorCounter = null;
}
return new CursorLoader(getActivity(),
HistoryContract.genContentUri(getActivity()),
new String[] { HistoryContract._COUNT }, selection, null,
null);
}// mLoaderIdHistoryCounter
return null;
}// onCreateLoader()
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onLoadFinished() -- data = " + data);
if (loader.getId() == mLoaderIdHistoryData) {
mSearchView.setEnabled(true);
mHistoryCursorAdapter.changeCursor(data);
for (int i = 0; i < mHistoryCursorAdapter.getGroupCount(); i++)
mListView.expandGroup(i);
/*
* Views visibilities. Always call these to make sure all views are
* in right visibilities.
*/
mHandler.removeCallbacksAndMessages(null);
mViewLoading.setVisibility(View.GONE);
mViewGroupListView.setVisibility(View.VISIBLE);
mListView.post(new Runnable() {
@Override
public void run() {
mListView.setSelection(-1);
}
});
}// mLoaderIdHistoryData
else if (loader.getId() == mLoaderIdHistoryCounter) {
if (mCursorCounter != null)
mCursorCounter.close();
mCursorCounter = data;
if (mCursorCounter.moveToFirst()) {
if (mItemCount < 0)
getLoaderManager().restartLoader(mLoaderIdHistoryData,
null, this);
mItemCount = mCursorCounter.getInt(mCursorCounter
.getColumnIndex(HistoryContract._COUNT));
mPageCount = (int) Math.ceil((float) mItemCount
/ mMaxItemsPerPage);
mBtnNext.setEnabled(mCurrentPage < mPageCount - 1);
mBtnPrev.setEnabled(mCurrentPage > 0);
} else {
mBtnNext.setEnabled(false);
mBtnPrev.setEnabled(false);
}
}// mLoaderIdHistoryCounter
enableControls(true);
}// onLoadFinished()
@Override
public void onLoaderReset(Loader<Cursor> loader) {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "onLoaderReset()");
if (loader.getId() == mLoaderIdHistoryData) {
mHistoryCursorAdapter.changeCursor(null);
mViewLoading.setVisibility(View.VISIBLE);
}// mLoaderIdHistoryData
else if (loader.getId() == mLoaderIdHistoryCounter) {
/*
* NOTE: if using an adapter, set its cursor to null to release
* memory.
*/
if (mCursorCounter != null) {
mCursorCounter.close();
mCursorCounter = null;
}
}// mLoaderIdHistoryCounter
}// onLoaderReset()
/**
* Loads content view from XML and init controls.
*
* @param inflater
* {@link LayoutInflater}.
* @param container
* {@link ViewGroup}.
*/
private View initContentView(LayoutInflater inflater, ViewGroup container) {
/*
* LOADS CONTROLS
*/
View mainView = inflater.inflate(R.layout.afc_viewgroup_history,
container, false);
mBtnSearch = mainView.findViewById(R.id.afc_button_search);
mViewGroupListView = mainView.findViewById(R.id.afc_viewgroup_listview);
mListView = (ExpandableListView) mainView
.findViewById(R.id.afc_listview);
mSearchView = (AfcSearchView) mainView
.findViewById(R.id.afc_afc_search_view);
mBtnNext = mainView.findViewById(R.id.afc_button_go_forward);
mBtnPrev = mainView.findViewById(R.id.afc_button_go_back);
mViewLoading = mainView.findViewById(R.id.afc_view_loading);
/*
* INITIALIZES CONTROLS
*/
if (mBtnSearch != null) {
mBtnSearch.setOnClickListener(mBtnSearchOnClickListener);
mBtnSearch.setVisibility(View.VISIBLE);
}
mSearchView.setOnQueryTextListener(mSearchViewOnQueryTextListener);
mSearchView.setOnStateChangeListener(mSearchViewOnStateChangeListener);
mListView.setEmptyView(mainView.findViewById(R.id.afc_empty_view));
mListView.setOnChildClickListener(mListViewOnChildClickListener);
mListView.setOnItemLongClickListener(mListViewOnItemLongClickListener);
initListViewGestureListener();
mHistoryCursorAdapter = new HistoryCursorAdapter(getActivity());
mListView.setAdapter(mHistoryCursorAdapter);
/*
* Default states of button navigators in XML are disabled, so we just
* set their listeners here.
*/
for (View v : new View[] { mBtnNext, mBtnPrev })
v.setOnTouchListener(mBtnNextPrevOnTouchListener);
return mainView;
}// initContentView()
/**
* As the name means.
*/
private void initListViewGestureListener() {
GestureUtils.setupGestureDetector(mListView,
new GestureUtils.SimpleOnGestureListener() {
@Override
public boolean onFling(View view, Object data,
FlingDirection flingDirection) {
if (!(data instanceof Cursor))
return false;
List<Integer> ids = new ArrayList<Integer>();
final int historyId = ((Cursor) data)
.getInt(((Cursor) data)
.getColumnIndex(HistoryContract._ID));
if (mHistoryCursorAdapter.isSelected(historyId))
ids.addAll(mHistoryCursorAdapter
.getSelectedItemIds());
else
ids.add(historyId);
if (ids.size() <= 1)
mHistoryCursorAdapter.markItemAsDeleted(historyId,
true);
else
mHistoryCursorAdapter
.markSelectedItemsAsDeleted(true);
final StringBuilder sb = new StringBuilder(String
.format("%s in (",
DbUtils.SQLITE_FTS_COLUMN_ROW_ID));
for (int id : ids)
sb.append(Integer.toString(id)).append(',');
sb.setCharAt(sb.length() - 1, ')');
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
getActivity().getContentResolver().delete(
HistoryContract
.genContentUri(getActivity()),
sb.toString(), null);
}
}, DisplayPrefs.DELAY_TIME_FOR_VERY_SHORT_ANIMATION);
return true;
}// onFling()
});
}// initListViewGestureListener()
/**
* Enables/ disables search view, button navigators' listeners (the
* listeners are DB querying related)...
*
* @param enabled
* {@code true} or {@code false}.
*/
private void enableControls(boolean enabled) {
/*
* If the user is typing, disabling search view will turn off the
* keyboard. So don't do that.
*/
// mSearchView.setEnabled(enabled);
for (View v : new View[] { mBtnNext, mBtnPrev }) {
v.setOnClickListener(enabled ? mBtnNextPrevOnClickListener : null);
v.setOnLongClickListener(enabled ? mBtnNextPrevOnLongClickListener
: null);
}
}// enableButtonNavigatorsListeners()
/**
* Asks user to confirm to clear history.
*/
private void doConfirmClearHistory() {
Dlg.confirmYesno(getActivity(),
getString(R.string.afc_msg_confirm_clear_history),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
getActivity().getContentResolver().delete(
HistoryContract.genContentUri(getActivity()),
null, null);
if (getDialog() != null)
getDialog().dismiss();
}// onClick()
});
}// doConfirmClearHistory()
/**
* Checks if the search view is on or off.
*
* @return {@code true} or {@code false}.
*/
private boolean isSearchViewOn() {
return mSearchView.getVisibility() == View.VISIBLE
&& !mSearchView.isIconified();
}// isSearchViewShowing()
/**
* Shows search view and opens up search components.
*/
private void switchOnSearchView() {
if (mBtnSearch != null)
mBtnSearch.setVisibility(View.GONE);
mSearchView.setVisibility(View.VISIBLE);
if (mSearchView.isIconified())
mSearchView.open();
}// switchOnSearchView()
/**
* Hides the search view and closes its components.
*/
private void switchOffSearchView() {
if (mBtnSearch != null)
mBtnSearch.setVisibility(View.VISIBLE);
mSearchView.setVisibility(View.GONE);
if (!mSearchView.isIconified())
mSearchView.close();
}// switchOffSearchView()
/*
* LISTENERS
*/
private final Runnable mViewLoadingShower = new Runnable() {
@Override
public void run() {
if (isAdded()) {
mViewGroupListView.setVisibility(View.GONE);
mViewLoading.setVisibility(View.VISIBLE);
}
}// run()
};// mViewLoadingShower
/**
* Sets {@code listener}.
*
* @param listener
* {@link OnHistoryItemClickListener}.
*/
public void setOnHistoryItemClickListener(
OnHistoryItemClickListener listener) {
mOnHistoryItemClickListener = listener;
}// setOnHistoryItemClickListener()
/**
* Gets an {@link OnHistoryItemClickListener}.
*
* @return the listener.
*/
public OnHistoryItemClickListener getOnHistoryItemClickListener() {
return mOnHistoryItemClickListener;
}// getOnHistoryItemClickListener()
/*
* CONTROLS' LISTENERS.
*/
/**
* Handles when user presses the search key, then opens up search view.
*/
private final DialogInterface.OnKeyListener mDialogOnKeyListener = new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_SEARCH) {
if (event.getAction() == KeyEvent.ACTION_UP) {
if (isSearchViewOn())
switchOffSearchView();
else
switchOnSearchView();
}
return true;
}
return false;
}// onKey()
};// mDialogOnKeyListener
private final View.OnClickListener mBtnSearchOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switchOnSearchView();
}// onClick()
};// mBtnSearchOnClickListener
private final AfcSearchView.OnQueryTextListener mSearchViewOnQueryTextListener = new AfcSearchView.OnQueryTextListener() {
@Override
public void onQueryTextSubmit(String query) {
if (!isAdded())
return;
try {
mHistoryCursorAdapter.setSearchText(query != null ? query
.trim() : null);
/*
* Sets total item count to -1, then restarts the counter, it
* will restart the data loader.
*/
mItemCount = -1;
getLoaderManager().restartLoader(mLoaderIdHistoryCounter, null,
HistoryFragment.this);
} catch (Throwable t) {
Log.e(CLASSNAME, "onQueryTextSubmit() >> " + t);
t.printStackTrace();
}
}// onQueryTextSubmit()
};// mSearchViewOnQueryTextListener
private final AfcSearchView.OnStateChangeListener mSearchViewOnStateChangeListener = new AfcSearchView.OnStateChangeListener() {
@Override
public void onOpen() {
// do nothing
}// onOpen()
@Override
public void onClose() {
switchOffSearchView();
if (!TextUtils.isEmpty(mHistoryCursorAdapter.getSearchText())
|| !TextUtils.isEmpty(mSearchView.getSearchText())) {
mHistoryCursorAdapter.setSearchText(null);
/*
* Sets total item count to -1, then restarts the counter, it
* will restart the data loader.
*/
mItemCount = -1;
getLoaderManager().restartLoader(mLoaderIdHistoryCounter, null,
HistoryFragment.this);
}
}// onClose()
};// mSearchViewOnStateChangeListener
private final View.OnClickListener mBtnNextPrevOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Ui.showSoftKeyboard(mSearchView, false);
if (v.getId() == R.id.afc_button_go_forward)
mCurrentPage++;
else if (v.getId() == R.id.afc_button_go_back)
mCurrentPage--;
getLoaderManager().restartLoader(mLoaderIdHistoryData, null,
HistoryFragment.this);
}// onClick()
};// mBtnNextPrevOnClickListener
private final View.OnLongClickListener mBtnNextPrevOnLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Ui.showSoftKeyboard(mSearchView, false);
if (v.getId() == R.id.afc_button_go_forward)
mCurrentPage = Integer.MAX_VALUE;
else if (v.getId() == R.id.afc_button_go_back)
mCurrentPage = 0;
getLoaderManager().restartLoader(mLoaderIdHistoryData, null,
HistoryFragment.this);
return true;
}// onLongClick()
};// mBtnNextPrevOnLongClickListener
private final View.OnTouchListener mBtnNextPrevOnTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
v.postDelayed(new Runnable() {
@Override
public void run() {
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, "BtnNextPrev -- TOUCH ACTION_UP");
if (isAdded()) {
mBtnNext.setEnabled(mCurrentPage < mPageCount - 1);
mBtnPrev.setEnabled(mCurrentPage > 0);
}
}// run()
}, DisplayPrefs.DELAY_TIME_FOR_VERY_SHORT_ANIMATION);
}
return false;
}// onTouch()
};// mBtnNextPrevOnTouchListener
private final ExpandableListView.OnChildClickListener mListViewOnChildClickListener = new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
if (getOnHistoryItemClickListener() != null) {
Cursor cursor = mHistoryCursorAdapter.getChild(groupPosition,
childPosition);
getOnHistoryItemClickListener()
.onItemClick(
cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_PROVIDER_ID)),
Uri.parse(cursor.getString(cursor
.getColumnIndex(HistoryContract.COLUMN_URI))));
}
if (getDialog() != null)
getDialog().dismiss();
return true;
}// onChildClick()
};// mListViewOnChildClickListener
private final AdapterView.OnItemLongClickListener mListViewOnItemLongClickListener = new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
switch (ExpandableListView.getPackedPositionType(id)) {
case ExpandableListView.PACKED_POSITION_TYPE_GROUP:
final int iGroup = ExpandableListView
.getPackedPositionGroup(mListView
.getExpandableListPosition(position));
if (!mListView.isGroupExpanded(iGroup))
return false;
if (BuildConfig.DEBUG)
Log.d(CLASSNAME, String.format(
"onItemLongClick() -- group = %,d", iGroup));
ContextMenuUtils.showContextMenu(getActivity(), 0,
R.string.afc_title_advanced_selection,
HistoryCursorAdapter.ADVANCED_SELECTION_OPTIONS,
new ContextMenuUtils.OnMenuItemClickListener() {
@Override
public void onClick(final int resId) {
if (resId == R.string.afc_cmd_advanced_selection_all)
mHistoryCursorAdapter.selectAll(iGroup,
true);
else if (resId == R.string.afc_cmd_advanced_selection_none)
mHistoryCursorAdapter.selectAll(iGroup,
false);
else if (resId == R.string.afc_cmd_advanced_selection_invert)
mHistoryCursorAdapter
.invertSelection(iGroup);
}// onClick()
});
return true;// PACKED_POSITION_TYPE_GROUP
case ExpandableListView.PACKED_POSITION_TYPE_CHILD:
return false;// PACKED_POSITION_TYPE_CHILD
}
return false;
}// onItemLongClick()
};// mListViewOnItemLongClickListener
}