mirror of
https://github.com/moparisthebest/keepass2android
synced 2025-01-11 05:28:34 -05:00
Bookmarks and history removed
This commit is contained in:
parent
848f99562c
commit
5c49a7fcb1
@ -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"
|
||||
|
@ -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>
|
@ -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>
|
@ -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"
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
@ -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()
|
||||
}
|
@ -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()
|
||||
}
|
@ -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()
|
||||
}
|
@ -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
|
||||
}
|
@ -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()
|
||||
}
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user