From 23caec047182a85869f56c9ca0ae9125227734fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sat, 25 May 2013 22:48:11 +0200 Subject: move ActionBarSherlock lib, add gradle build files --- .gitignore | 29 +- OpenPGP-Keychain-API-Demo/.gitignore | 23 +- OpenPGP-Keychain-API-Lib/.gitignore | 23 +- OpenPGP-Keychain/.gitignore | 22 +- .../android-libs/ActionBarSherlock/.gitignore | 23 - .../ActionBarSherlock/AndroidManifest.xml | 6 - .../android-libs/ActionBarSherlock/README.md | 15 - .../android-libs/ActionBarSherlock/build.xml | 92 - .../ActionBarSherlock/libs/android-support-v4.jar | Bin 271754 -> 0 bytes .../android-libs/ActionBarSherlock/pom.xml | 148 -- .../ActionBarSherlock/proguard-project.txt | 20 - .../ActionBarSherlock/project.properties | 12 - .../abs__primary_text_disable_only_holo_dark.xml | 20 - .../abs__primary_text_disable_only_holo_light.xml | 21 - .../res/color/abs__primary_text_holo_dark.xml | 24 - .../res/color/abs__primary_text_holo_light.xml | 26 - .../abs__ab_bottom_solid_dark_holo.9.png | Bin 144 -> 0 bytes .../abs__ab_bottom_solid_inverse_holo.9.png | Bin 138 -> 0 bytes .../abs__ab_bottom_solid_light_holo.9.png | Bin 144 -> 0 bytes .../abs__ab_bottom_transparent_dark_holo.9.png | Bin 135 -> 0 bytes .../abs__ab_bottom_transparent_light_holo.9.png | Bin 134 -> 0 bytes .../abs__ab_share_pack_holo_dark.9.png | Bin 2863 -> 0 bytes .../abs__ab_share_pack_holo_light.9.png | Bin 2859 -> 0 bytes .../drawable-hdpi/abs__ab_solid_dark_holo.9.png | Bin 146 -> 0 bytes .../drawable-hdpi/abs__ab_solid_light_holo.9.png | Bin 145 -> 0 bytes .../drawable-hdpi/abs__ab_solid_shadow_holo.9.png | Bin 192 -> 0 bytes .../abs__ab_stacked_solid_dark_holo.9.png | Bin 146 -> 0 bytes .../abs__ab_stacked_solid_light_holo.9.png | Bin 146 -> 0 bytes .../abs__ab_stacked_transparent_dark_holo.9.png | Bin 139 -> 0 bytes .../abs__ab_stacked_transparent_light_holo.9.png | Bin 133 -> 0 bytes .../abs__ab_transparent_dark_holo.9.png | Bin 155 -> 0 bytes .../abs__ab_transparent_light_holo.9.png | Bin 145 -> 0 bytes .../abs__btn_cab_done_default_holo_dark.9.png | Bin 104 -> 0 bytes .../abs__btn_cab_done_default_holo_light.9.png | Bin 102 -> 0 bytes .../abs__btn_cab_done_focused_holo_dark.9.png | Bin 112 -> 0 bytes .../abs__btn_cab_done_focused_holo_light.9.png | Bin 108 -> 0 bytes .../abs__btn_cab_done_pressed_holo_dark.9.png | Bin 110 -> 0 bytes .../abs__btn_cab_done_pressed_holo_light.9.png | Bin 108 -> 0 bytes .../abs__cab_background_bottom_holo_dark.9.png | Bin 149 -> 0 bytes .../abs__cab_background_bottom_holo_light.9.png | Bin 145 -> 0 bytes .../abs__cab_background_top_holo_dark.9.png | Bin 147 -> 0 bytes .../abs__cab_background_top_holo_light.9.png | Bin 147 -> 0 bytes .../drawable-hdpi/abs__dialog_full_holo_dark.9.png | Bin 1414 -> 0 bytes .../abs__dialog_full_holo_light.9.png | Bin 1537 -> 0 bytes .../drawable-hdpi/abs__ic_ab_back_holo_dark.png | Bin 602 -> 0 bytes .../drawable-hdpi/abs__ic_ab_back_holo_light.png | Bin 546 -> 0 bytes .../drawable-hdpi/abs__ic_cab_done_holo_dark.png | Bin 713 -> 0 bytes .../drawable-hdpi/abs__ic_cab_done_holo_light.png | Bin 737 -> 0 bytes .../res/drawable-hdpi/abs__ic_clear_disabled.png | Bin 1774 -> 0 bytes .../res/drawable-hdpi/abs__ic_clear_normal.png | Bin 1945 -> 0 bytes ...bs__ic_clear_search_api_disabled_holo_light.png | Bin 1504 -> 0 bytes .../abs__ic_clear_search_api_holo_light.png | Bin 1540 -> 0 bytes .../res/drawable-hdpi/abs__ic_go.png | Bin 1415 -> 0 bytes .../abs__ic_go_search_api_holo_light.png | Bin 1252 -> 0 bytes .../abs__ic_menu_moreoverflow_normal_holo_dark.png | Bin 144 -> 0 bytes ...abs__ic_menu_moreoverflow_normal_holo_light.png | Bin 148 -> 0 bytes .../drawable-hdpi/abs__ic_menu_share_holo_dark.png | Bin 467 -> 0 bytes .../abs__ic_menu_share_holo_light.png | Bin 505 -> 0 bytes .../res/drawable-hdpi/abs__ic_search.png | Bin 2280 -> 0 bytes .../abs__ic_search_api_holo_light.png | Bin 2271 -> 0 bytes .../res/drawable-hdpi/abs__ic_voice_search.png | Bin 2070 -> 0 bytes .../abs__ic_voice_search_api_holo_light.png | Bin 1833 -> 0 bytes .../drawable-hdpi/abs__list_activated_holo.9.png | Bin 154 -> 0 bytes .../abs__list_divider_holo_dark.9.png | Bin 78 -> 0 bytes .../abs__list_divider_holo_light.9.png | Bin 76 -> 0 bytes .../res/drawable-hdpi/abs__list_focused_holo.9.png | Bin 159 -> 0 bytes .../drawable-hdpi/abs__list_longpressed_holo.9.png | Bin 154 -> 0 bytes .../abs__list_pressed_holo_dark.9.png | Bin 159 -> 0 bytes .../abs__list_pressed_holo_light.9.png | Bin 159 -> 0 bytes .../abs__list_selector_disabled_holo_dark.9.png | Bin 189 -> 0 bytes .../abs__list_selector_disabled_holo_light.9.png | Bin 189 -> 0 bytes .../abs__menu_dropdown_panel_holo_dark.9.png | Bin 922 -> 0 bytes .../abs__menu_dropdown_panel_holo_light.9.png | Bin 1061 -> 0 bytes .../drawable-hdpi/abs__progress_bg_holo_dark.9.png | Bin 178 -> 0 bytes .../abs__progress_bg_holo_light.9.png | Bin 174 -> 0 bytes .../abs__progress_primary_holo_dark.9.png | Bin 917 -> 0 bytes .../abs__progress_primary_holo_light.9.png | Bin 917 -> 0 bytes .../abs__progress_secondary_holo_dark.9.png | Bin 188 -> 0 bytes .../abs__progress_secondary_holo_light.9.png | Bin 188 -> 0 bytes .../drawable-hdpi/abs__spinner_48_inner_holo.png | Bin 2081 -> 0 bytes .../drawable-hdpi/abs__spinner_48_outer_holo.png | Bin 1811 -> 0 bytes .../abs__spinner_ab_default_holo_dark.9.png | Bin 311 -> 0 bytes .../abs__spinner_ab_default_holo_light.9.png | Bin 312 -> 0 bytes .../abs__spinner_ab_disabled_holo_dark.9.png | Bin 306 -> 0 bytes .../abs__spinner_ab_disabled_holo_light.9.png | Bin 306 -> 0 bytes .../abs__spinner_ab_focused_holo_dark.9.png | Bin 524 -> 0 bytes .../abs__spinner_ab_focused_holo_light.9.png | Bin 523 -> 0 bytes .../abs__spinner_ab_pressed_holo_dark.9.png | Bin 464 -> 0 bytes .../abs__spinner_ab_pressed_holo_light.9.png | Bin 458 -> 0 bytes .../abs__tab_selected_focused_holo.9.png | Bin 147 -> 0 bytes .../res/drawable-hdpi/abs__tab_selected_holo.9.png | Bin 148 -> 0 bytes .../abs__tab_selected_pressed_holo.9.png | Bin 147 -> 0 bytes .../abs__tab_unselected_pressed_holo.9.png | Bin 145 -> 0 bytes .../abs__textfield_search_default_holo_dark.9.png | Bin 110 -> 0 bytes .../abs__textfield_search_default_holo_light.9.png | Bin 105 -> 0 bytes ..._textfield_search_right_default_holo_dark.9.png | Bin 108 -> 0 bytes ...textfield_search_right_default_holo_light.9.png | Bin 103 -> 0 bytes ...textfield_search_right_selected_holo_dark.9.png | Bin 114 -> 0 bytes ...extfield_search_right_selected_holo_light.9.png | Bin 111 -> 0 bytes .../abs__textfield_search_selected_holo_dark.9.png | Bin 114 -> 0 bytes ...abs__textfield_search_selected_holo_light.9.png | Bin 112 -> 0 bytes .../abs__ab_bottom_solid_dark_holo.9.png | Bin 134 -> 0 bytes .../abs__ab_bottom_solid_inverse_holo.9.png | Bin 129 -> 0 bytes .../abs__ab_bottom_solid_light_holo.9.png | Bin 134 -> 0 bytes .../abs__ab_bottom_transparent_dark_holo.9.png | Bin 123 -> 0 bytes .../abs__ab_bottom_transparent_light_holo.9.png | Bin 123 -> 0 bytes .../abs__ab_share_pack_holo_dark.9.png | Bin 2849 -> 0 bytes .../abs__ab_share_pack_holo_light.9.png | Bin 191 -> 0 bytes .../drawable-mdpi/abs__ab_solid_dark_holo.9.png | Bin 133 -> 0 bytes .../drawable-mdpi/abs__ab_solid_light_holo.9.png | Bin 133 -> 0 bytes .../drawable-mdpi/abs__ab_solid_shadow_holo.9.png | Bin 168 -> 0 bytes .../abs__ab_stacked_solid_dark_holo.9.png | Bin 134 -> 0 bytes .../abs__ab_stacked_solid_light_holo.9.png | Bin 133 -> 0 bytes .../abs__ab_stacked_transparent_dark_holo.9.png | Bin 127 -> 0 bytes .../abs__ab_stacked_transparent_light_holo.9.png | Bin 123 -> 0 bytes .../abs__ab_transparent_dark_holo.9.png | Bin 139 -> 0 bytes .../abs__ab_transparent_light_holo.9.png | Bin 133 -> 0 bytes .../abs__btn_cab_done_default_holo_dark.9.png | Bin 101 -> 0 bytes .../abs__btn_cab_done_default_holo_light.9.png | Bin 99 -> 0 bytes .../abs__btn_cab_done_focused_holo_dark.9.png | Bin 109 -> 0 bytes .../abs__btn_cab_done_focused_holo_light.9.png | Bin 105 -> 0 bytes .../abs__btn_cab_done_pressed_holo_dark.9.png | Bin 107 -> 0 bytes .../abs__btn_cab_done_pressed_holo_light.9.png | Bin 105 -> 0 bytes .../abs__cab_background_bottom_holo_dark.9.png | Bin 127 -> 0 bytes .../abs__cab_background_bottom_holo_light.9.png | Bin 124 -> 0 bytes .../abs__cab_background_top_holo_dark.9.png | Bin 130 -> 0 bytes .../abs__cab_background_top_holo_light.9.png | Bin 128 -> 0 bytes .../drawable-mdpi/abs__dialog_full_holo_dark.9.png | Bin 882 -> 0 bytes .../abs__dialog_full_holo_light.9.png | Bin 1003 -> 0 bytes .../drawable-mdpi/abs__ic_ab_back_holo_dark.png | Bin 466 -> 0 bytes .../drawable-mdpi/abs__ic_ab_back_holo_light.png | Bin 438 -> 0 bytes .../drawable-mdpi/abs__ic_cab_done_holo_dark.png | Bin 566 -> 0 bytes .../drawable-mdpi/abs__ic_cab_done_holo_light.png | Bin 552 -> 0 bytes .../res/drawable-mdpi/abs__ic_clear_disabled.png | Bin 1775 -> 0 bytes .../res/drawable-mdpi/abs__ic_clear_normal.png | Bin 1869 -> 0 bytes ...bs__ic_clear_search_api_disabled_holo_light.png | Bin 740 -> 0 bytes .../abs__ic_clear_search_api_holo_light.png | Bin 743 -> 0 bytes .../res/drawable-mdpi/abs__ic_go.png | Bin 1538 -> 0 bytes .../abs__ic_go_search_api_holo_light.png | Bin 570 -> 0 bytes .../abs__ic_menu_moreoverflow_normal_holo_dark.png | Bin 122 -> 0 bytes ...abs__ic_menu_moreoverflow_normal_holo_light.png | Bin 131 -> 0 bytes .../drawable-mdpi/abs__ic_menu_share_holo_dark.png | Bin 332 -> 0 bytes .../abs__ic_menu_share_holo_light.png | Bin 355 -> 0 bytes .../res/drawable-mdpi/abs__ic_search.png | Bin 2280 -> 0 bytes .../abs__ic_search_api_holo_light.png | Bin 1541 -> 0 bytes .../res/drawable-mdpi/abs__ic_voice_search.png | Bin 1937 -> 0 bytes .../abs__ic_voice_search_api_holo_light.png | Bin 794 -> 0 bytes .../drawable-mdpi/abs__list_activated_holo.9.png | Bin 151 -> 0 bytes .../abs__list_divider_holo_dark.9.png | Bin 78 -> 0 bytes .../abs__list_divider_holo_light.9.png | Bin 76 -> 0 bytes .../res/drawable-mdpi/abs__list_focused_holo.9.png | Bin 158 -> 0 bytes .../drawable-mdpi/abs__list_longpressed_holo.9.png | Bin 151 -> 0 bytes .../abs__list_pressed_holo_dark.9.png | Bin 158 -> 0 bytes .../abs__list_pressed_holo_light.9.png | Bin 158 -> 0 bytes .../abs__list_selector_disabled_holo_dark.9.png | Bin 172 -> 0 bytes .../abs__list_selector_disabled_holo_light.9.png | Bin 171 -> 0 bytes .../abs__menu_dropdown_panel_holo_dark.9.png | Bin 651 -> 0 bytes .../abs__menu_dropdown_panel_holo_light.9.png | Bin 720 -> 0 bytes .../drawable-mdpi/abs__progress_bg_holo_dark.9.png | Bin 165 -> 0 bytes .../abs__progress_bg_holo_light.9.png | Bin 159 -> 0 bytes .../abs__progress_primary_holo_dark.9.png | Bin 572 -> 0 bytes .../abs__progress_primary_holo_light.9.png | Bin 572 -> 0 bytes .../abs__progress_secondary_holo_dark.9.png | Bin 170 -> 0 bytes .../abs__progress_secondary_holo_light.9.png | Bin 170 -> 0 bytes .../drawable-mdpi/abs__spinner_48_inner_holo.png | Bin 1336 -> 0 bytes .../drawable-mdpi/abs__spinner_48_outer_holo.png | Bin 1165 -> 0 bytes .../abs__spinner_ab_default_holo_dark.9.png | Bin 254 -> 0 bytes .../abs__spinner_ab_default_holo_light.9.png | Bin 255 -> 0 bytes .../abs__spinner_ab_disabled_holo_dark.9.png | Bin 249 -> 0 bytes .../abs__spinner_ab_disabled_holo_light.9.png | Bin 249 -> 0 bytes .../abs__spinner_ab_focused_holo_dark.9.png | Bin 417 -> 0 bytes .../abs__spinner_ab_focused_holo_light.9.png | Bin 424 -> 0 bytes .../abs__spinner_ab_pressed_holo_dark.9.png | Bin 370 -> 0 bytes .../abs__spinner_ab_pressed_holo_light.9.png | Bin 370 -> 0 bytes .../abs__tab_selected_focused_holo.9.png | Bin 148 -> 0 bytes .../res/drawable-mdpi/abs__tab_selected_holo.9.png | Bin 151 -> 0 bytes .../abs__tab_selected_pressed_holo.9.png | Bin 150 -> 0 bytes .../abs__tab_unselected_pressed_holo.9.png | Bin 155 -> 0 bytes .../abs__textfield_search_default_holo_dark.9.png | Bin 106 -> 0 bytes .../abs__textfield_search_default_holo_light.9.png | Bin 100 -> 0 bytes ..._textfield_search_right_default_holo_dark.9.png | Bin 105 -> 0 bytes ...textfield_search_right_default_holo_light.9.png | Bin 98 -> 0 bytes ...textfield_search_right_selected_holo_dark.9.png | Bin 107 -> 0 bytes ...extfield_search_right_selected_holo_light.9.png | Bin 107 -> 0 bytes .../abs__textfield_search_selected_holo_dark.9.png | Bin 109 -> 0 bytes ...abs__textfield_search_selected_holo_light.9.png | Bin 109 -> 0 bytes .../res/drawable-v11/abs__progress_medium_holo.xml | 34 - .../abs__ab_bottom_solid_dark_holo.9.png | Bin 165 -> 0 bytes .../abs__ab_bottom_solid_inverse_holo.9.png | Bin 157 -> 0 bytes .../abs__ab_bottom_solid_light_holo.9.png | Bin 166 -> 0 bytes .../abs__ab_bottom_transparent_dark_holo.9.png | Bin 153 -> 0 bytes .../abs__ab_bottom_transparent_light_holo.9.png | Bin 152 -> 0 bytes .../abs__ab_share_pack_holo_dark.9.png | Bin 2878 -> 0 bytes .../abs__ab_share_pack_holo_light.9.png | Bin 2873 -> 0 bytes .../drawable-xhdpi/abs__ab_solid_dark_holo.9.png | Bin 163 -> 0 bytes .../drawable-xhdpi/abs__ab_solid_light_holo.9.png | Bin 163 -> 0 bytes .../drawable-xhdpi/abs__ab_solid_shadow_holo.9.png | Bin 290 -> 0 bytes .../abs__ab_stacked_solid_dark_holo.9.png | Bin 163 -> 0 bytes .../abs__ab_stacked_solid_light_holo.9.png | Bin 163 -> 0 bytes .../abs__ab_stacked_transparent_dark_holo.9.png | Bin 158 -> 0 bytes .../abs__ab_stacked_transparent_light_holo.9.png | Bin 152 -> 0 bytes .../abs__ab_transparent_dark_holo.9.png | Bin 171 -> 0 bytes .../abs__ab_transparent_light_holo.9.png | Bin 160 -> 0 bytes .../abs__btn_cab_done_default_holo_dark.9.png | Bin 109 -> 0 bytes .../abs__btn_cab_done_default_holo_light.9.png | Bin 108 -> 0 bytes .../abs__btn_cab_done_focused_holo_dark.9.png | Bin 112 -> 0 bytes .../abs__btn_cab_done_focused_holo_light.9.png | Bin 113 -> 0 bytes .../abs__btn_cab_done_pressed_holo_dark.9.png | Bin 115 -> 0 bytes .../abs__btn_cab_done_pressed_holo_light.9.png | Bin 113 -> 0 bytes .../abs__cab_background_bottom_holo_dark.9.png | Bin 166 -> 0 bytes .../abs__cab_background_bottom_holo_light.9.png | Bin 161 -> 0 bytes .../abs__cab_background_top_holo_dark.9.png | Bin 174 -> 0 bytes .../abs__cab_background_top_holo_light.9.png | Bin 161 -> 0 bytes .../abs__dialog_full_holo_dark.9.png | Bin 2159 -> 0 bytes .../abs__dialog_full_holo_light.9.png | Bin 2302 -> 0 bytes .../drawable-xhdpi/abs__ic_ab_back_holo_dark.png | Bin 741 -> 0 bytes .../drawable-xhdpi/abs__ic_ab_back_holo_light.png | Bin 661 -> 0 bytes .../drawable-xhdpi/abs__ic_cab_done_holo_dark.png | Bin 970 -> 0 bytes .../drawable-xhdpi/abs__ic_cab_done_holo_light.png | Bin 915 -> 0 bytes .../res/drawable-xhdpi/abs__ic_clear_disabled.png | Bin 2531 -> 0 bytes ...bs__ic_clear_search_api_disabled_holo_light.png | Bin 1315 -> 0 bytes .../abs__ic_clear_search_api_holo_light.png | Bin 1447 -> 0 bytes .../res/drawable-xhdpi/abs__ic_go.png | Bin 1983 -> 0 bytes .../abs__ic_go_search_api_holo_light.png | Bin 836 -> 0 bytes .../abs__ic_menu_moreoverflow_normal_holo_dark.png | Bin 167 -> 0 bytes ...abs__ic_menu_moreoverflow_normal_holo_light.png | Bin 184 -> 0 bytes .../abs__ic_menu_share_holo_dark.png | Bin 699 -> 0 bytes .../abs__ic_menu_share_holo_light.png | Bin 935 -> 0 bytes .../res/drawable-xhdpi/abs__ic_search.png | Bin 3784 -> 0 bytes .../abs__ic_search_api_holo_light.png | Bin 3037 -> 0 bytes .../res/drawable-xhdpi/abs__ic_voice_search.png | Bin 3053 -> 0 bytes .../abs__ic_voice_search_api_holo_light.png | Bin 1414 -> 0 bytes .../drawable-xhdpi/abs__list_activated_holo.9.png | Bin 158 -> 0 bytes .../abs__list_divider_holo_dark.9.png | Bin 83 -> 0 bytes .../abs__list_divider_holo_light.9.png | Bin 83 -> 0 bytes .../drawable-xhdpi/abs__list_focused_holo.9.png | Bin 163 -> 0 bytes .../abs__list_longpressed_holo.9.png | Bin 158 -> 0 bytes .../abs__list_pressed_holo_dark.9.png | Bin 163 -> 0 bytes .../abs__list_pressed_holo_light.9.png | Bin 163 -> 0 bytes .../abs__list_selector_disabled_holo_dark.9.png | Bin 190 -> 0 bytes .../abs__list_selector_disabled_holo_light.9.png | Bin 188 -> 0 bytes .../abs__menu_dropdown_panel_holo_dark.9.png | Bin 1362 -> 0 bytes .../abs__menu_dropdown_panel_holo_light.9.png | Bin 1551 -> 0 bytes .../abs__progress_bg_holo_dark.9.png | Bin 174 -> 0 bytes .../abs__progress_bg_holo_light.9.png | Bin 172 -> 0 bytes .../abs__progress_primary_holo_dark.9.png | Bin 1309 -> 0 bytes .../abs__progress_primary_holo_light.9.png | Bin 1309 -> 0 bytes .../abs__progress_secondary_holo_dark.9.png | Bin 184 -> 0 bytes .../abs__progress_secondary_holo_light.9.png | Bin 184 -> 0 bytes .../drawable-xhdpi/abs__spinner_48_inner_holo.png | Bin 2769 -> 0 bytes .../drawable-xhdpi/abs__spinner_48_outer_holo.png | Bin 2432 -> 0 bytes .../abs__spinner_ab_default_holo_dark.9.png | Bin 395 -> 0 bytes .../abs__spinner_ab_default_holo_light.9.png | Bin 394 -> 0 bytes .../abs__spinner_ab_disabled_holo_dark.9.png | Bin 381 -> 0 bytes .../abs__spinner_ab_disabled_holo_light.9.png | Bin 381 -> 0 bytes .../abs__spinner_ab_focused_holo_dark.9.png | Bin 680 -> 0 bytes .../abs__spinner_ab_focused_holo_light.9.png | Bin 671 -> 0 bytes .../abs__spinner_ab_pressed_holo_dark.9.png | Bin 609 -> 0 bytes .../abs__spinner_ab_pressed_holo_light.9.png | Bin 602 -> 0 bytes .../abs__tab_selected_focused_holo.9.png | Bin 147 -> 0 bytes .../drawable-xhdpi/abs__tab_selected_holo.9.png | Bin 153 -> 0 bytes .../abs__tab_selected_pressed_holo.9.png | Bin 147 -> 0 bytes .../abs__tab_unselected_pressed_holo.9.png | Bin 149 -> 0 bytes .../abs__textfield_search_default_holo_dark.9.png | Bin 126 -> 0 bytes .../abs__textfield_search_default_holo_light.9.png | Bin 126 -> 0 bytes ..._textfield_search_right_default_holo_dark.9.png | Bin 125 -> 0 bytes ...textfield_search_right_default_holo_light.9.png | Bin 127 -> 0 bytes ...textfield_search_right_selected_holo_dark.9.png | Bin 128 -> 0 bytes ...extfield_search_right_selected_holo_light.9.png | Bin 128 -> 0 bytes .../abs__textfield_search_selected_holo_dark.9.png | Bin 114 -> 0 bytes ...abs__textfield_search_selected_holo_light.9.png | Bin 126 -> 0 bytes .../abs__activated_background_holo_dark.xml | 20 - .../abs__activated_background_holo_light.xml | 20 - .../res/drawable/abs__btn_cab_done_holo_dark.xml | 24 - .../res/drawable/abs__btn_cab_done_holo_light.xml | 24 - .../res/drawable/abs__ic_clear.xml | 22 - .../res/drawable/abs__ic_clear_holo_light.xml | 22 - .../abs__ic_menu_moreoverflow_holo_dark.xml | 18 - .../abs__ic_menu_moreoverflow_holo_light.xml | 18 - .../drawable/abs__item_background_holo_dark.xml | 26 - .../drawable/abs__item_background_holo_light.xml | 26 - ...st_selector_background_transition_holo_dark.xml | 20 - ...t_selector_background_transition_holo_light.xml | 20 - .../res/drawable/abs__list_selector_holo_dark.xml | 27 - .../res/drawable/abs__list_selector_holo_light.xml | 28 - .../abs__progress_horizontal_holo_dark.xml | 32 - .../abs__progress_horizontal_holo_light.xml | 32 - .../res/drawable/abs__progress_medium_holo.xml | 34 - .../res/drawable/abs__search_dropdown_dark.xml | 22 - .../res/drawable/abs__search_dropdown_light.xml | 22 - .../res/drawable/abs__spinner_ab_holo_dark.xml | 25 - .../res/drawable/abs__spinner_ab_holo_light.xml | 25 - .../res/drawable/abs__tab_indicator_ab_holo.xml | 34 - .../abs__textfield_searchview_holo_dark.xml | 22 - .../abs__textfield_searchview_holo_light.xml | 22 - .../abs__textfield_searchview_right_holo_dark.xml | 22 - .../abs__textfield_searchview_right_holo_light.xml | 22 - .../layout-large/abs__action_mode_close_item.xml | 40 - .../layout-v14/sherlock_spinner_dropdown_item.xml | 26 - .../res/layout-v14/sherlock_spinner_item.xml | 26 - .../res/layout-xlarge/abs__screen_action_bar.xml | 50 - .../abs__screen_action_bar_overlay.xml | 49 - .../res/layout/abs__action_bar_home.xml | 38 - .../res/layout/abs__action_bar_tab.xml | 7 - .../res/layout/abs__action_bar_tab_bar_view.xml | 6 - .../res/layout/abs__action_bar_title_item.xml | 50 - .../res/layout/abs__action_menu_item_layout.xml | 56 - .../res/layout/abs__action_menu_layout.xml | 23 - .../res/layout/abs__action_mode_bar.xml | 24 - .../res/layout/abs__action_mode_close_item.xml | 31 - .../res/layout/abs__activity_chooser_view.xml | 70 - .../abs__activity_chooser_view_list_item.xml | 53 - .../res/layout/abs__dialog_title_holo.xml | 46 - .../res/layout/abs__list_menu_item_checkbox.xml | 26 - .../res/layout/abs__list_menu_item_icon.xml | 28 - .../res/layout/abs__list_menu_item_layout.xml | 59 - .../res/layout/abs__list_menu_item_radio.xml | 24 - .../res/layout/abs__popup_menu_item_layout.xml | 60 - .../res/layout/abs__screen_action_bar.xml | 57 - .../res/layout/abs__screen_action_bar_overlay.xml | 59 - .../res/layout/abs__screen_simple.xml | 38 - .../abs__screen_simple_overlay_action_mode.xml | 38 - .../abs__search_dropdown_item_icons_2line.xml | 89 - .../res/layout/abs__search_view.xml | 159 -- .../res/layout/abs__simple_dropdown_hint.xml | 29 - .../res/layout/sherlock_spinner_dropdown_item.xml | 26 - .../res/layout/sherlock_spinner_item.xml | 26 - .../res/values-land/abs__dimens.xml | 33 - .../res/values-large-hdpi-1024x600/abs__dimens.xml | 33 - .../abs__dimens.xml | 33 - .../abs__dimens.xml | 33 - .../res/values-large-mdpi-1024x600/abs__dimens.xml | 36 - .../res/values-large/abs__dimens.xml | 29 - .../res/values-sw600dp/abs__bools.xml | 19 - .../res/values-sw600dp/abs__dimens.xml | 38 - .../res/values-v11/abs__themes.xml | 12 - .../res/values-v14/abs__styles.xml | 123 -- .../res/values-v14/abs__themes.xml | 34 - .../res/values-w360dp/abs__dimens.xml | 22 - .../res/values-w480dp/abs__bools.xml | 22 - .../res/values-w480dp/abs__config.xml | 29 - .../res/values-w500dp/abs__dimens.xml | 22 - .../res/values-w600dp/abs__dimens.xml | 22 - .../res/values-xlarge/abs__dimens.xml | 45 - .../ActionBarSherlock/res/values/abs__attrs.xml | 432 ----- .../ActionBarSherlock/res/values/abs__bools.xml | 22 - .../ActionBarSherlock/res/values/abs__colors.xml | 27 - .../ActionBarSherlock/res/values/abs__config.xml | 43 - .../ActionBarSherlock/res/values/abs__dimens.xml | 67 - .../ActionBarSherlock/res/values/abs__ids.xml | 26 - .../ActionBarSherlock/res/values/abs__strings.xml | 53 - .../ActionBarSherlock/res/values/abs__styles.xml | 412 ----- .../ActionBarSherlock/res/values/abs__themes.xml | 239 --- .../src/android/support/v4/app/Watson.java | 144 -- .../com/actionbarsherlock/ActionBarSherlock.java | 794 --------- .../src/com/actionbarsherlock/app/ActionBar.java | 956 ----------- .../actionbarsherlock/app/SherlockActivity.java | 270 --- .../app/SherlockDialogFragment.java | 68 - .../app/SherlockExpandableListActivity.java | 259 --- .../actionbarsherlock/app/SherlockFragment.java | 68 - .../app/SherlockFragmentActivity.java | 303 ---- .../app/SherlockListActivity.java | 270 --- .../app/SherlockListFragment.java | 68 - .../app/SherlockPreferenceActivity.java | 270 --- .../internal/ActionBarSherlockCompat.java | 1203 ------------- .../internal/ActionBarSherlockNative.java | 336 ---- .../internal/ResourcesCompat.java | 95 - .../internal/app/ActionBarImpl.java | 1026 ----------- .../internal/app/ActionBarWrapper.java | 468 ----- .../nineoldandroids/animation/Animator.java | 278 --- .../animation/AnimatorListenerAdapter.java | 54 - .../nineoldandroids/animation/AnimatorSet.java | 1111 ------------ .../nineoldandroids/animation/FloatEvaluator.java | 42 - .../animation/FloatKeyframeSet.java | 136 -- .../nineoldandroids/animation/IntEvaluator.java | 42 - .../nineoldandroids/animation/IntKeyframeSet.java | 135 -- .../nineoldandroids/animation/Keyframe.java | 361 ---- .../nineoldandroids/animation/KeyframeSet.java | 227 --- .../nineoldandroids/animation/ObjectAnimator.java | 491 ------ .../animation/PropertyValuesHolder.java | 1012 ----------- .../nineoldandroids/animation/TypeEvaluator.java | 44 - .../nineoldandroids/animation/ValueAnimator.java | 1265 -------------- .../nineoldandroids/view/NineViewGroup.java | 79 - .../view/animation/AnimatorProxy.java | 212 --- .../nineoldandroids/widget/NineFrameLayout.java | 57 - .../widget/NineHorizontalScrollView.java | 41 - .../nineoldandroids/widget/NineLinearLayout.java | 57 - .../internal/view/ActionProviderWrapper.java | 40 - .../internal/view/StandaloneActionMode.java | 148 -- .../view/View_HasStateListenerSupport.java | 6 - .../view/View_OnAttachStateChangeListener.java | 8 - .../internal/view/menu/ActionMenu.java | 264 --- .../internal/view/menu/ActionMenuItem.java | 278 --- .../internal/view/menu/ActionMenuItemView.java | 295 ---- .../internal/view/menu/ActionMenuPresenter.java | 714 -------- .../internal/view/menu/ActionMenuView.java | 575 ------- .../internal/view/menu/BaseMenuPresenter.java | 231 --- .../internal/view/menu/ListMenuItemView.java | 278 --- .../internal/view/menu/MenuBuilder.java | 1335 --------------- .../internal/view/menu/MenuItemImpl.java | 647 ------- .../internal/view/menu/MenuItemWrapper.java | 310 ---- .../internal/view/menu/MenuPopupHelper.java | 376 ---- .../internal/view/menu/MenuPresenter.java | 148 -- .../internal/view/menu/MenuView.java | 120 -- .../internal/view/menu/MenuWrapper.java | 185 -- .../internal/view/menu/SubMenuBuilder.java | 134 -- .../internal/view/menu/SubMenuWrapper.java | 72 - .../internal/widget/AbsActionBarView.java | 291 ---- .../internal/widget/ActionBarContainer.java | 258 --- .../internal/widget/ActionBarContextView.java | 518 ------ .../internal/widget/ActionBarView.java | 1548 ----------------- .../internal/widget/CapitalizingButton.java | 40 - .../internal/widget/CapitalizingTextView.java | 50 - .../widget/CollapsibleActionViewWrapper.java | 30 - .../internal/widget/FakeDialogPhoneWindow.java | 64 - .../internal/widget/IcsAbsSpinner.java | 479 ------ .../internal/widget/IcsAdapterView.java | 1160 ------------- .../internal/widget/IcsColorDrawable.java | 41 - .../internal/widget/IcsLinearLayout.java | 410 ----- .../internal/widget/IcsListPopupWindow.java | 644 ------- .../internal/widget/IcsProgressBar.java | 1193 ------------- .../internal/widget/IcsSpinner.java | 703 -------- .../actionbarsherlock/internal/widget/IcsView.java | 21 - .../internal/widget/ScrollingTabContainerView.java | 546 ------ .../src/com/actionbarsherlock/view/ActionMode.java | 224 --- .../com/actionbarsherlock/view/ActionProvider.java | 170 -- .../view/CollapsibleActionView.java | 39 - .../src/com/actionbarsherlock/view/Menu.java | 447 ----- .../com/actionbarsherlock/view/MenuInflater.java | 495 ------ .../src/com/actionbarsherlock/view/MenuItem.java | 598 ------- .../src/com/actionbarsherlock/view/SubMenu.java | 110 -- .../src/com/actionbarsherlock/view/Window.java | 65 - .../widget/ActivityChooserModel.java | 1104 ------------ .../widget/ActivityChooserView.java | 827 --------- .../com/actionbarsherlock/widget/SearchView.java | 1811 -------------------- .../widget/ShareActionProvider.java | 316 ---- .../widget/SuggestionsAdapter.java | 733 -------- .../internal/ManifestParsingTest.java | 37 - OpenPGP-Keychain/build.gradle | 63 + OpenPGP-Keychain/libs/android-support-v4.jar | Bin 0 -> 271754 bytes OpenPGP-Keychain/project.properties | 2 +- libraries/ActionBarSherlock/.gitignore | 30 + libraries/ActionBarSherlock/AndroidManifest.xml | 6 + libraries/ActionBarSherlock/README.md | 15 + libraries/ActionBarSherlock/build.gradle | 27 + libraries/ActionBarSherlock/build.xml | 92 + .../ActionBarSherlock/libs/android-support-v4.jar | Bin 0 -> 271754 bytes libraries/ActionBarSherlock/pom.xml | 148 ++ libraries/ActionBarSherlock/proguard-project.txt | 20 + libraries/ActionBarSherlock/project.properties | 12 + .../abs__primary_text_disable_only_holo_dark.xml | 20 + .../abs__primary_text_disable_only_holo_light.xml | 21 + .../res/color/abs__primary_text_holo_dark.xml | 24 + .../res/color/abs__primary_text_holo_light.xml | 26 + .../abs__ab_bottom_solid_dark_holo.9.png | Bin 0 -> 144 bytes .../abs__ab_bottom_solid_inverse_holo.9.png | Bin 0 -> 138 bytes .../abs__ab_bottom_solid_light_holo.9.png | Bin 0 -> 144 bytes .../abs__ab_bottom_transparent_dark_holo.9.png | Bin 0 -> 135 bytes .../abs__ab_bottom_transparent_light_holo.9.png | Bin 0 -> 134 bytes .../abs__ab_share_pack_holo_dark.9.png | Bin 0 -> 2863 bytes .../abs__ab_share_pack_holo_light.9.png | Bin 0 -> 2859 bytes .../drawable-hdpi/abs__ab_solid_dark_holo.9.png | Bin 0 -> 146 bytes .../drawable-hdpi/abs__ab_solid_light_holo.9.png | Bin 0 -> 145 bytes .../drawable-hdpi/abs__ab_solid_shadow_holo.9.png | Bin 0 -> 192 bytes .../abs__ab_stacked_solid_dark_holo.9.png | Bin 0 -> 146 bytes .../abs__ab_stacked_solid_light_holo.9.png | Bin 0 -> 146 bytes .../abs__ab_stacked_transparent_dark_holo.9.png | Bin 0 -> 139 bytes .../abs__ab_stacked_transparent_light_holo.9.png | Bin 0 -> 133 bytes .../abs__ab_transparent_dark_holo.9.png | Bin 0 -> 155 bytes .../abs__ab_transparent_light_holo.9.png | Bin 0 -> 145 bytes .../abs__btn_cab_done_default_holo_dark.9.png | Bin 0 -> 104 bytes .../abs__btn_cab_done_default_holo_light.9.png | Bin 0 -> 102 bytes .../abs__btn_cab_done_focused_holo_dark.9.png | Bin 0 -> 112 bytes .../abs__btn_cab_done_focused_holo_light.9.png | Bin 0 -> 108 bytes .../abs__btn_cab_done_pressed_holo_dark.9.png | Bin 0 -> 110 bytes .../abs__btn_cab_done_pressed_holo_light.9.png | Bin 0 -> 108 bytes .../abs__cab_background_bottom_holo_dark.9.png | Bin 0 -> 149 bytes .../abs__cab_background_bottom_holo_light.9.png | Bin 0 -> 145 bytes .../abs__cab_background_top_holo_dark.9.png | Bin 0 -> 147 bytes .../abs__cab_background_top_holo_light.9.png | Bin 0 -> 147 bytes .../drawable-hdpi/abs__dialog_full_holo_dark.9.png | Bin 0 -> 1414 bytes .../abs__dialog_full_holo_light.9.png | Bin 0 -> 1537 bytes .../drawable-hdpi/abs__ic_ab_back_holo_dark.png | Bin 0 -> 602 bytes .../drawable-hdpi/abs__ic_ab_back_holo_light.png | Bin 0 -> 546 bytes .../drawable-hdpi/abs__ic_cab_done_holo_dark.png | Bin 0 -> 713 bytes .../drawable-hdpi/abs__ic_cab_done_holo_light.png | Bin 0 -> 737 bytes .../res/drawable-hdpi/abs__ic_clear_disabled.png | Bin 0 -> 1774 bytes .../res/drawable-hdpi/abs__ic_clear_normal.png | Bin 0 -> 1945 bytes ...bs__ic_clear_search_api_disabled_holo_light.png | Bin 0 -> 1504 bytes .../abs__ic_clear_search_api_holo_light.png | Bin 0 -> 1540 bytes .../res/drawable-hdpi/abs__ic_go.png | Bin 0 -> 1415 bytes .../abs__ic_go_search_api_holo_light.png | Bin 0 -> 1252 bytes .../abs__ic_menu_moreoverflow_normal_holo_dark.png | Bin 0 -> 144 bytes ...abs__ic_menu_moreoverflow_normal_holo_light.png | Bin 0 -> 148 bytes .../drawable-hdpi/abs__ic_menu_share_holo_dark.png | Bin 0 -> 467 bytes .../abs__ic_menu_share_holo_light.png | Bin 0 -> 505 bytes .../res/drawable-hdpi/abs__ic_search.png | Bin 0 -> 2280 bytes .../abs__ic_search_api_holo_light.png | Bin 0 -> 2271 bytes .../res/drawable-hdpi/abs__ic_voice_search.png | Bin 0 -> 2070 bytes .../abs__ic_voice_search_api_holo_light.png | Bin 0 -> 1833 bytes .../drawable-hdpi/abs__list_activated_holo.9.png | Bin 0 -> 154 bytes .../abs__list_divider_holo_dark.9.png | Bin 0 -> 78 bytes .../abs__list_divider_holo_light.9.png | Bin 0 -> 76 bytes .../res/drawable-hdpi/abs__list_focused_holo.9.png | Bin 0 -> 159 bytes .../drawable-hdpi/abs__list_longpressed_holo.9.png | Bin 0 -> 154 bytes .../abs__list_pressed_holo_dark.9.png | Bin 0 -> 159 bytes .../abs__list_pressed_holo_light.9.png | Bin 0 -> 159 bytes .../abs__list_selector_disabled_holo_dark.9.png | Bin 0 -> 189 bytes .../abs__list_selector_disabled_holo_light.9.png | Bin 0 -> 189 bytes .../abs__menu_dropdown_panel_holo_dark.9.png | Bin 0 -> 922 bytes .../abs__menu_dropdown_panel_holo_light.9.png | Bin 0 -> 1061 bytes .../drawable-hdpi/abs__progress_bg_holo_dark.9.png | Bin 0 -> 178 bytes .../abs__progress_bg_holo_light.9.png | Bin 0 -> 174 bytes .../abs__progress_primary_holo_dark.9.png | Bin 0 -> 917 bytes .../abs__progress_primary_holo_light.9.png | Bin 0 -> 917 bytes .../abs__progress_secondary_holo_dark.9.png | Bin 0 -> 188 bytes .../abs__progress_secondary_holo_light.9.png | Bin 0 -> 188 bytes .../drawable-hdpi/abs__spinner_48_inner_holo.png | Bin 0 -> 2081 bytes .../drawable-hdpi/abs__spinner_48_outer_holo.png | Bin 0 -> 1811 bytes .../abs__spinner_ab_default_holo_dark.9.png | Bin 0 -> 311 bytes .../abs__spinner_ab_default_holo_light.9.png | Bin 0 -> 312 bytes .../abs__spinner_ab_disabled_holo_dark.9.png | Bin 0 -> 306 bytes .../abs__spinner_ab_disabled_holo_light.9.png | Bin 0 -> 306 bytes .../abs__spinner_ab_focused_holo_dark.9.png | Bin 0 -> 524 bytes .../abs__spinner_ab_focused_holo_light.9.png | Bin 0 -> 523 bytes .../abs__spinner_ab_pressed_holo_dark.9.png | Bin 0 -> 464 bytes .../abs__spinner_ab_pressed_holo_light.9.png | Bin 0 -> 458 bytes .../abs__tab_selected_focused_holo.9.png | Bin 0 -> 147 bytes .../res/drawable-hdpi/abs__tab_selected_holo.9.png | Bin 0 -> 148 bytes .../abs__tab_selected_pressed_holo.9.png | Bin 0 -> 147 bytes .../abs__tab_unselected_pressed_holo.9.png | Bin 0 -> 145 bytes .../abs__textfield_search_default_holo_dark.9.png | Bin 0 -> 110 bytes .../abs__textfield_search_default_holo_light.9.png | Bin 0 -> 105 bytes ..._textfield_search_right_default_holo_dark.9.png | Bin 0 -> 108 bytes ...textfield_search_right_default_holo_light.9.png | Bin 0 -> 103 bytes ...textfield_search_right_selected_holo_dark.9.png | Bin 0 -> 114 bytes ...extfield_search_right_selected_holo_light.9.png | Bin 0 -> 111 bytes .../abs__textfield_search_selected_holo_dark.9.png | Bin 0 -> 114 bytes ...abs__textfield_search_selected_holo_light.9.png | Bin 0 -> 112 bytes .../abs__ab_bottom_solid_dark_holo.9.png | Bin 0 -> 134 bytes .../abs__ab_bottom_solid_inverse_holo.9.png | Bin 0 -> 129 bytes .../abs__ab_bottom_solid_light_holo.9.png | Bin 0 -> 134 bytes .../abs__ab_bottom_transparent_dark_holo.9.png | Bin 0 -> 123 bytes .../abs__ab_bottom_transparent_light_holo.9.png | Bin 0 -> 123 bytes .../abs__ab_share_pack_holo_dark.9.png | Bin 0 -> 2849 bytes .../abs__ab_share_pack_holo_light.9.png | Bin 0 -> 191 bytes .../drawable-mdpi/abs__ab_solid_dark_holo.9.png | Bin 0 -> 133 bytes .../drawable-mdpi/abs__ab_solid_light_holo.9.png | Bin 0 -> 133 bytes .../drawable-mdpi/abs__ab_solid_shadow_holo.9.png | Bin 0 -> 168 bytes .../abs__ab_stacked_solid_dark_holo.9.png | Bin 0 -> 134 bytes .../abs__ab_stacked_solid_light_holo.9.png | Bin 0 -> 133 bytes .../abs__ab_stacked_transparent_dark_holo.9.png | Bin 0 -> 127 bytes .../abs__ab_stacked_transparent_light_holo.9.png | Bin 0 -> 123 bytes .../abs__ab_transparent_dark_holo.9.png | Bin 0 -> 139 bytes .../abs__ab_transparent_light_holo.9.png | Bin 0 -> 133 bytes .../abs__btn_cab_done_default_holo_dark.9.png | Bin 0 -> 101 bytes .../abs__btn_cab_done_default_holo_light.9.png | Bin 0 -> 99 bytes .../abs__btn_cab_done_focused_holo_dark.9.png | Bin 0 -> 109 bytes .../abs__btn_cab_done_focused_holo_light.9.png | Bin 0 -> 105 bytes .../abs__btn_cab_done_pressed_holo_dark.9.png | Bin 0 -> 107 bytes .../abs__btn_cab_done_pressed_holo_light.9.png | Bin 0 -> 105 bytes .../abs__cab_background_bottom_holo_dark.9.png | Bin 0 -> 127 bytes .../abs__cab_background_bottom_holo_light.9.png | Bin 0 -> 124 bytes .../abs__cab_background_top_holo_dark.9.png | Bin 0 -> 130 bytes .../abs__cab_background_top_holo_light.9.png | Bin 0 -> 128 bytes .../drawable-mdpi/abs__dialog_full_holo_dark.9.png | Bin 0 -> 882 bytes .../abs__dialog_full_holo_light.9.png | Bin 0 -> 1003 bytes .../drawable-mdpi/abs__ic_ab_back_holo_dark.png | Bin 0 -> 466 bytes .../drawable-mdpi/abs__ic_ab_back_holo_light.png | Bin 0 -> 438 bytes .../drawable-mdpi/abs__ic_cab_done_holo_dark.png | Bin 0 -> 566 bytes .../drawable-mdpi/abs__ic_cab_done_holo_light.png | Bin 0 -> 552 bytes .../res/drawable-mdpi/abs__ic_clear_disabled.png | Bin 0 -> 1775 bytes .../res/drawable-mdpi/abs__ic_clear_normal.png | Bin 0 -> 1869 bytes ...bs__ic_clear_search_api_disabled_holo_light.png | Bin 0 -> 740 bytes .../abs__ic_clear_search_api_holo_light.png | Bin 0 -> 743 bytes .../res/drawable-mdpi/abs__ic_go.png | Bin 0 -> 1538 bytes .../abs__ic_go_search_api_holo_light.png | Bin 0 -> 570 bytes .../abs__ic_menu_moreoverflow_normal_holo_dark.png | Bin 0 -> 122 bytes ...abs__ic_menu_moreoverflow_normal_holo_light.png | Bin 0 -> 131 bytes .../drawable-mdpi/abs__ic_menu_share_holo_dark.png | Bin 0 -> 332 bytes .../abs__ic_menu_share_holo_light.png | Bin 0 -> 355 bytes .../res/drawable-mdpi/abs__ic_search.png | Bin 0 -> 2280 bytes .../abs__ic_search_api_holo_light.png | Bin 0 -> 1541 bytes .../res/drawable-mdpi/abs__ic_voice_search.png | Bin 0 -> 1937 bytes .../abs__ic_voice_search_api_holo_light.png | Bin 0 -> 794 bytes .../drawable-mdpi/abs__list_activated_holo.9.png | Bin 0 -> 151 bytes .../abs__list_divider_holo_dark.9.png | Bin 0 -> 78 bytes .../abs__list_divider_holo_light.9.png | Bin 0 -> 76 bytes .../res/drawable-mdpi/abs__list_focused_holo.9.png | Bin 0 -> 158 bytes .../drawable-mdpi/abs__list_longpressed_holo.9.png | Bin 0 -> 151 bytes .../abs__list_pressed_holo_dark.9.png | Bin 0 -> 158 bytes .../abs__list_pressed_holo_light.9.png | Bin 0 -> 158 bytes .../abs__list_selector_disabled_holo_dark.9.png | Bin 0 -> 172 bytes .../abs__list_selector_disabled_holo_light.9.png | Bin 0 -> 171 bytes .../abs__menu_dropdown_panel_holo_dark.9.png | Bin 0 -> 651 bytes .../abs__menu_dropdown_panel_holo_light.9.png | Bin 0 -> 720 bytes .../drawable-mdpi/abs__progress_bg_holo_dark.9.png | Bin 0 -> 165 bytes .../abs__progress_bg_holo_light.9.png | Bin 0 -> 159 bytes .../abs__progress_primary_holo_dark.9.png | Bin 0 -> 572 bytes .../abs__progress_primary_holo_light.9.png | Bin 0 -> 572 bytes .../abs__progress_secondary_holo_dark.9.png | Bin 0 -> 170 bytes .../abs__progress_secondary_holo_light.9.png | Bin 0 -> 170 bytes .../drawable-mdpi/abs__spinner_48_inner_holo.png | Bin 0 -> 1336 bytes .../drawable-mdpi/abs__spinner_48_outer_holo.png | Bin 0 -> 1165 bytes .../abs__spinner_ab_default_holo_dark.9.png | Bin 0 -> 254 bytes .../abs__spinner_ab_default_holo_light.9.png | Bin 0 -> 255 bytes .../abs__spinner_ab_disabled_holo_dark.9.png | Bin 0 -> 249 bytes .../abs__spinner_ab_disabled_holo_light.9.png | Bin 0 -> 249 bytes .../abs__spinner_ab_focused_holo_dark.9.png | Bin 0 -> 417 bytes .../abs__spinner_ab_focused_holo_light.9.png | Bin 0 -> 424 bytes .../abs__spinner_ab_pressed_holo_dark.9.png | Bin 0 -> 370 bytes .../abs__spinner_ab_pressed_holo_light.9.png | Bin 0 -> 370 bytes .../abs__tab_selected_focused_holo.9.png | Bin 0 -> 148 bytes .../res/drawable-mdpi/abs__tab_selected_holo.9.png | Bin 0 -> 151 bytes .../abs__tab_selected_pressed_holo.9.png | Bin 0 -> 150 bytes .../abs__tab_unselected_pressed_holo.9.png | Bin 0 -> 155 bytes .../abs__textfield_search_default_holo_dark.9.png | Bin 0 -> 106 bytes .../abs__textfield_search_default_holo_light.9.png | Bin 0 -> 100 bytes ..._textfield_search_right_default_holo_dark.9.png | Bin 0 -> 105 bytes ...textfield_search_right_default_holo_light.9.png | Bin 0 -> 98 bytes ...textfield_search_right_selected_holo_dark.9.png | Bin 0 -> 107 bytes ...extfield_search_right_selected_holo_light.9.png | Bin 0 -> 107 bytes .../abs__textfield_search_selected_holo_dark.9.png | Bin 0 -> 109 bytes ...abs__textfield_search_selected_holo_light.9.png | Bin 0 -> 109 bytes .../res/drawable-v11/abs__progress_medium_holo.xml | 34 + .../abs__ab_bottom_solid_dark_holo.9.png | Bin 0 -> 165 bytes .../abs__ab_bottom_solid_inverse_holo.9.png | Bin 0 -> 157 bytes .../abs__ab_bottom_solid_light_holo.9.png | Bin 0 -> 166 bytes .../abs__ab_bottom_transparent_dark_holo.9.png | Bin 0 -> 153 bytes .../abs__ab_bottom_transparent_light_holo.9.png | Bin 0 -> 152 bytes .../abs__ab_share_pack_holo_dark.9.png | Bin 0 -> 2878 bytes .../abs__ab_share_pack_holo_light.9.png | Bin 0 -> 2873 bytes .../drawable-xhdpi/abs__ab_solid_dark_holo.9.png | Bin 0 -> 163 bytes .../drawable-xhdpi/abs__ab_solid_light_holo.9.png | Bin 0 -> 163 bytes .../drawable-xhdpi/abs__ab_solid_shadow_holo.9.png | Bin 0 -> 290 bytes .../abs__ab_stacked_solid_dark_holo.9.png | Bin 0 -> 163 bytes .../abs__ab_stacked_solid_light_holo.9.png | Bin 0 -> 163 bytes .../abs__ab_stacked_transparent_dark_holo.9.png | Bin 0 -> 158 bytes .../abs__ab_stacked_transparent_light_holo.9.png | Bin 0 -> 152 bytes .../abs__ab_transparent_dark_holo.9.png | Bin 0 -> 171 bytes .../abs__ab_transparent_light_holo.9.png | Bin 0 -> 160 bytes .../abs__btn_cab_done_default_holo_dark.9.png | Bin 0 -> 109 bytes .../abs__btn_cab_done_default_holo_light.9.png | Bin 0 -> 108 bytes .../abs__btn_cab_done_focused_holo_dark.9.png | Bin 0 -> 112 bytes .../abs__btn_cab_done_focused_holo_light.9.png | Bin 0 -> 113 bytes .../abs__btn_cab_done_pressed_holo_dark.9.png | Bin 0 -> 115 bytes .../abs__btn_cab_done_pressed_holo_light.9.png | Bin 0 -> 113 bytes .../abs__cab_background_bottom_holo_dark.9.png | Bin 0 -> 166 bytes .../abs__cab_background_bottom_holo_light.9.png | Bin 0 -> 161 bytes .../abs__cab_background_top_holo_dark.9.png | Bin 0 -> 174 bytes .../abs__cab_background_top_holo_light.9.png | Bin 0 -> 161 bytes .../abs__dialog_full_holo_dark.9.png | Bin 0 -> 2159 bytes .../abs__dialog_full_holo_light.9.png | Bin 0 -> 2302 bytes .../drawable-xhdpi/abs__ic_ab_back_holo_dark.png | Bin 0 -> 741 bytes .../drawable-xhdpi/abs__ic_ab_back_holo_light.png | Bin 0 -> 661 bytes .../drawable-xhdpi/abs__ic_cab_done_holo_dark.png | Bin 0 -> 970 bytes .../drawable-xhdpi/abs__ic_cab_done_holo_light.png | Bin 0 -> 915 bytes .../res/drawable-xhdpi/abs__ic_clear_disabled.png | Bin 0 -> 2531 bytes ...bs__ic_clear_search_api_disabled_holo_light.png | Bin 0 -> 1315 bytes .../abs__ic_clear_search_api_holo_light.png | Bin 0 -> 1447 bytes .../res/drawable-xhdpi/abs__ic_go.png | Bin 0 -> 1983 bytes .../abs__ic_go_search_api_holo_light.png | Bin 0 -> 836 bytes .../abs__ic_menu_moreoverflow_normal_holo_dark.png | Bin 0 -> 167 bytes ...abs__ic_menu_moreoverflow_normal_holo_light.png | Bin 0 -> 184 bytes .../abs__ic_menu_share_holo_dark.png | Bin 0 -> 699 bytes .../abs__ic_menu_share_holo_light.png | Bin 0 -> 935 bytes .../res/drawable-xhdpi/abs__ic_search.png | Bin 0 -> 3784 bytes .../abs__ic_search_api_holo_light.png | Bin 0 -> 3037 bytes .../res/drawable-xhdpi/abs__ic_voice_search.png | Bin 0 -> 3053 bytes .../abs__ic_voice_search_api_holo_light.png | Bin 0 -> 1414 bytes .../drawable-xhdpi/abs__list_activated_holo.9.png | Bin 0 -> 158 bytes .../abs__list_divider_holo_dark.9.png | Bin 0 -> 83 bytes .../abs__list_divider_holo_light.9.png | Bin 0 -> 83 bytes .../drawable-xhdpi/abs__list_focused_holo.9.png | Bin 0 -> 163 bytes .../abs__list_longpressed_holo.9.png | Bin 0 -> 158 bytes .../abs__list_pressed_holo_dark.9.png | Bin 0 -> 163 bytes .../abs__list_pressed_holo_light.9.png | Bin 0 -> 163 bytes .../abs__list_selector_disabled_holo_dark.9.png | Bin 0 -> 190 bytes .../abs__list_selector_disabled_holo_light.9.png | Bin 0 -> 188 bytes .../abs__menu_dropdown_panel_holo_dark.9.png | Bin 0 -> 1362 bytes .../abs__menu_dropdown_panel_holo_light.9.png | Bin 0 -> 1551 bytes .../abs__progress_bg_holo_dark.9.png | Bin 0 -> 174 bytes .../abs__progress_bg_holo_light.9.png | Bin 0 -> 172 bytes .../abs__progress_primary_holo_dark.9.png | Bin 0 -> 1309 bytes .../abs__progress_primary_holo_light.9.png | Bin 0 -> 1309 bytes .../abs__progress_secondary_holo_dark.9.png | Bin 0 -> 184 bytes .../abs__progress_secondary_holo_light.9.png | Bin 0 -> 184 bytes .../drawable-xhdpi/abs__spinner_48_inner_holo.png | Bin 0 -> 2769 bytes .../drawable-xhdpi/abs__spinner_48_outer_holo.png | Bin 0 -> 2432 bytes .../abs__spinner_ab_default_holo_dark.9.png | Bin 0 -> 395 bytes .../abs__spinner_ab_default_holo_light.9.png | Bin 0 -> 394 bytes .../abs__spinner_ab_disabled_holo_dark.9.png | Bin 0 -> 381 bytes .../abs__spinner_ab_disabled_holo_light.9.png | Bin 0 -> 381 bytes .../abs__spinner_ab_focused_holo_dark.9.png | Bin 0 -> 680 bytes .../abs__spinner_ab_focused_holo_light.9.png | Bin 0 -> 671 bytes .../abs__spinner_ab_pressed_holo_dark.9.png | Bin 0 -> 609 bytes .../abs__spinner_ab_pressed_holo_light.9.png | Bin 0 -> 602 bytes .../abs__tab_selected_focused_holo.9.png | Bin 0 -> 147 bytes .../drawable-xhdpi/abs__tab_selected_holo.9.png | Bin 0 -> 153 bytes .../abs__tab_selected_pressed_holo.9.png | Bin 0 -> 147 bytes .../abs__tab_unselected_pressed_holo.9.png | Bin 0 -> 149 bytes .../abs__textfield_search_default_holo_dark.9.png | Bin 0 -> 126 bytes .../abs__textfield_search_default_holo_light.9.png | Bin 0 -> 126 bytes ..._textfield_search_right_default_holo_dark.9.png | Bin 0 -> 125 bytes ...textfield_search_right_default_holo_light.9.png | Bin 0 -> 127 bytes ...textfield_search_right_selected_holo_dark.9.png | Bin 0 -> 128 bytes ...extfield_search_right_selected_holo_light.9.png | Bin 0 -> 128 bytes .../abs__textfield_search_selected_holo_dark.9.png | Bin 0 -> 114 bytes ...abs__textfield_search_selected_holo_light.9.png | Bin 0 -> 126 bytes .../abs__activated_background_holo_dark.xml | 20 + .../abs__activated_background_holo_light.xml | 20 + .../res/drawable/abs__btn_cab_done_holo_dark.xml | 24 + .../res/drawable/abs__btn_cab_done_holo_light.xml | 24 + .../res/drawable/abs__ic_clear.xml | 22 + .../res/drawable/abs__ic_clear_holo_light.xml | 22 + .../abs__ic_menu_moreoverflow_holo_dark.xml | 18 + .../abs__ic_menu_moreoverflow_holo_light.xml | 18 + .../drawable/abs__item_background_holo_dark.xml | 26 + .../drawable/abs__item_background_holo_light.xml | 26 + ...st_selector_background_transition_holo_dark.xml | 20 + ...t_selector_background_transition_holo_light.xml | 20 + .../res/drawable/abs__list_selector_holo_dark.xml | 27 + .../res/drawable/abs__list_selector_holo_light.xml | 28 + .../abs__progress_horizontal_holo_dark.xml | 32 + .../abs__progress_horizontal_holo_light.xml | 32 + .../res/drawable/abs__progress_medium_holo.xml | 34 + .../res/drawable/abs__search_dropdown_dark.xml | 22 + .../res/drawable/abs__search_dropdown_light.xml | 22 + .../res/drawable/abs__spinner_ab_holo_dark.xml | 25 + .../res/drawable/abs__spinner_ab_holo_light.xml | 25 + .../res/drawable/abs__tab_indicator_ab_holo.xml | 34 + .../abs__textfield_searchview_holo_dark.xml | 22 + .../abs__textfield_searchview_holo_light.xml | 22 + .../abs__textfield_searchview_right_holo_dark.xml | 22 + .../abs__textfield_searchview_right_holo_light.xml | 22 + .../layout-large/abs__action_mode_close_item.xml | 40 + .../layout-v14/sherlock_spinner_dropdown_item.xml | 26 + .../res/layout-v14/sherlock_spinner_item.xml | 26 + .../res/layout-xlarge/abs__screen_action_bar.xml | 50 + .../abs__screen_action_bar_overlay.xml | 49 + .../res/layout/abs__action_bar_home.xml | 38 + .../res/layout/abs__action_bar_tab.xml | 7 + .../res/layout/abs__action_bar_tab_bar_view.xml | 6 + .../res/layout/abs__action_bar_title_item.xml | 50 + .../res/layout/abs__action_menu_item_layout.xml | 56 + .../res/layout/abs__action_menu_layout.xml | 23 + .../res/layout/abs__action_mode_bar.xml | 24 + .../res/layout/abs__action_mode_close_item.xml | 31 + .../res/layout/abs__activity_chooser_view.xml | 70 + .../abs__activity_chooser_view_list_item.xml | 53 + .../res/layout/abs__dialog_title_holo.xml | 46 + .../res/layout/abs__list_menu_item_checkbox.xml | 26 + .../res/layout/abs__list_menu_item_icon.xml | 28 + .../res/layout/abs__list_menu_item_layout.xml | 59 + .../res/layout/abs__list_menu_item_radio.xml | 24 + .../res/layout/abs__popup_menu_item_layout.xml | 60 + .../res/layout/abs__screen_action_bar.xml | 57 + .../res/layout/abs__screen_action_bar_overlay.xml | 59 + .../res/layout/abs__screen_simple.xml | 38 + .../abs__screen_simple_overlay_action_mode.xml | 38 + .../abs__search_dropdown_item_icons_2line.xml | 89 + .../res/layout/abs__search_view.xml | 159 ++ .../res/layout/abs__simple_dropdown_hint.xml | 29 + .../res/layout/sherlock_spinner_dropdown_item.xml | 26 + .../res/layout/sherlock_spinner_item.xml | 26 + .../res/values-land/abs__dimens.xml | 33 + .../res/values-large-hdpi-1024x600/abs__dimens.xml | 33 + .../abs__dimens.xml | 33 + .../abs__dimens.xml | 33 + .../res/values-large-mdpi-1024x600/abs__dimens.xml | 36 + .../res/values-large/abs__dimens.xml | 29 + .../res/values-sw600dp/abs__bools.xml | 19 + .../res/values-sw600dp/abs__dimens.xml | 38 + .../res/values-v11/abs__themes.xml | 12 + .../res/values-v14/abs__styles.xml | 123 ++ .../res/values-v14/abs__themes.xml | 34 + .../res/values-w360dp/abs__dimens.xml | 22 + .../res/values-w480dp/abs__bools.xml | 22 + .../res/values-w480dp/abs__config.xml | 29 + .../res/values-w500dp/abs__dimens.xml | 22 + .../res/values-w600dp/abs__dimens.xml | 22 + .../res/values-xlarge/abs__dimens.xml | 45 + .../ActionBarSherlock/res/values/abs__attrs.xml | 432 +++++ .../ActionBarSherlock/res/values/abs__bools.xml | 22 + .../ActionBarSherlock/res/values/abs__colors.xml | 27 + .../ActionBarSherlock/res/values/abs__config.xml | 43 + .../ActionBarSherlock/res/values/abs__dimens.xml | 67 + .../ActionBarSherlock/res/values/abs__ids.xml | 26 + .../ActionBarSherlock/res/values/abs__strings.xml | 53 + .../ActionBarSherlock/res/values/abs__styles.xml | 412 +++++ .../ActionBarSherlock/res/values/abs__themes.xml | 239 +++ .../src/android/support/v4/app/Watson.java | 144 ++ .../com/actionbarsherlock/ActionBarSherlock.java | 794 +++++++++ .../src/com/actionbarsherlock/app/ActionBar.java | 956 +++++++++++ .../actionbarsherlock/app/SherlockActivity.java | 270 +++ .../app/SherlockDialogFragment.java | 68 + .../app/SherlockExpandableListActivity.java | 259 +++ .../actionbarsherlock/app/SherlockFragment.java | 68 + .../app/SherlockFragmentActivity.java | 303 ++++ .../app/SherlockListActivity.java | 270 +++ .../app/SherlockListFragment.java | 68 + .../app/SherlockPreferenceActivity.java | 270 +++ .../internal/ActionBarSherlockCompat.java | 1203 +++++++++++++ .../internal/ActionBarSherlockNative.java | 336 ++++ .../internal/ResourcesCompat.java | 95 + .../internal/app/ActionBarImpl.java | 1026 +++++++++++ .../internal/app/ActionBarWrapper.java | 468 +++++ .../nineoldandroids/animation/Animator.java | 278 +++ .../animation/AnimatorListenerAdapter.java | 54 + .../nineoldandroids/animation/AnimatorSet.java | 1111 ++++++++++++ .../nineoldandroids/animation/FloatEvaluator.java | 42 + .../animation/FloatKeyframeSet.java | 136 ++ .../nineoldandroids/animation/IntEvaluator.java | 42 + .../nineoldandroids/animation/IntKeyframeSet.java | 135 ++ .../nineoldandroids/animation/Keyframe.java | 361 ++++ .../nineoldandroids/animation/KeyframeSet.java | 227 +++ .../nineoldandroids/animation/ObjectAnimator.java | 491 ++++++ .../animation/PropertyValuesHolder.java | 1012 +++++++++++ .../nineoldandroids/animation/TypeEvaluator.java | 44 + .../nineoldandroids/animation/ValueAnimator.java | 1265 ++++++++++++++ .../nineoldandroids/view/NineViewGroup.java | 79 + .../view/animation/AnimatorProxy.java | 212 +++ .../nineoldandroids/widget/NineFrameLayout.java | 57 + .../widget/NineHorizontalScrollView.java | 41 + .../nineoldandroids/widget/NineLinearLayout.java | 57 + .../internal/view/ActionProviderWrapper.java | 40 + .../internal/view/StandaloneActionMode.java | 148 ++ .../view/View_HasStateListenerSupport.java | 6 + .../view/View_OnAttachStateChangeListener.java | 8 + .../internal/view/menu/ActionMenu.java | 264 +++ .../internal/view/menu/ActionMenuItem.java | 278 +++ .../internal/view/menu/ActionMenuItemView.java | 295 ++++ .../internal/view/menu/ActionMenuPresenter.java | 714 ++++++++ .../internal/view/menu/ActionMenuView.java | 575 +++++++ .../internal/view/menu/BaseMenuPresenter.java | 231 +++ .../internal/view/menu/ListMenuItemView.java | 278 +++ .../internal/view/menu/MenuBuilder.java | 1335 +++++++++++++++ .../internal/view/menu/MenuItemImpl.java | 647 +++++++ .../internal/view/menu/MenuItemWrapper.java | 310 ++++ .../internal/view/menu/MenuPopupHelper.java | 376 ++++ .../internal/view/menu/MenuPresenter.java | 148 ++ .../internal/view/menu/MenuView.java | 120 ++ .../internal/view/menu/MenuWrapper.java | 185 ++ .../internal/view/menu/SubMenuBuilder.java | 134 ++ .../internal/view/menu/SubMenuWrapper.java | 72 + .../internal/widget/AbsActionBarView.java | 291 ++++ .../internal/widget/ActionBarContainer.java | 258 +++ .../internal/widget/ActionBarContextView.java | 518 ++++++ .../internal/widget/ActionBarView.java | 1548 +++++++++++++++++ .../internal/widget/CapitalizingButton.java | 40 + .../internal/widget/CapitalizingTextView.java | 50 + .../widget/CollapsibleActionViewWrapper.java | 30 + .../internal/widget/FakeDialogPhoneWindow.java | 64 + .../internal/widget/IcsAbsSpinner.java | 479 ++++++ .../internal/widget/IcsAdapterView.java | 1160 +++++++++++++ .../internal/widget/IcsColorDrawable.java | 41 + .../internal/widget/IcsLinearLayout.java | 410 +++++ .../internal/widget/IcsListPopupWindow.java | 644 +++++++ .../internal/widget/IcsProgressBar.java | 1193 +++++++++++++ .../internal/widget/IcsSpinner.java | 703 ++++++++ .../actionbarsherlock/internal/widget/IcsView.java | 21 + .../internal/widget/ScrollingTabContainerView.java | 546 ++++++ .../src/com/actionbarsherlock/view/ActionMode.java | 224 +++ .../com/actionbarsherlock/view/ActionProvider.java | 170 ++ .../view/CollapsibleActionView.java | 39 + .../src/com/actionbarsherlock/view/Menu.java | 447 +++++ .../com/actionbarsherlock/view/MenuInflater.java | 495 ++++++ .../src/com/actionbarsherlock/view/MenuItem.java | 598 +++++++ .../src/com/actionbarsherlock/view/SubMenu.java | 110 ++ .../src/com/actionbarsherlock/view/Window.java | 65 + .../widget/ActivityChooserModel.java | 1104 ++++++++++++ .../widget/ActivityChooserView.java | 827 +++++++++ .../com/actionbarsherlock/widget/SearchView.java | 1811 ++++++++++++++++++++ .../widget/ShareActionProvider.java | 316 ++++ .../widget/SuggestionsAdapter.java | 733 ++++++++ .../internal/ManifestParsingTest.java | 37 + settings.gradle | 1 + 877 files changed, 37838 insertions(+), 37693 deletions(-) delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/.gitignore delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/AndroidManifest.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/README.md delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/build.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/libs/android-support-v4.jar delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/pom.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/proguard-project.txt delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/project.properties delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_home.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_layout.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_bar.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_item.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-land/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__bools.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v11/abs__themes.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w360dp/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__bools.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__config.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w500dp/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w600dp/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-xlarge/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__attrs.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__bools.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__colors.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__config.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__dimens.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__ids.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__strings.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__styles.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__themes.xml delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java delete mode 100644 OpenPGP-Keychain/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java create mode 100644 OpenPGP-Keychain/build.gradle create mode 100644 OpenPGP-Keychain/libs/android-support-v4.jar create mode 100644 libraries/ActionBarSherlock/.gitignore create mode 100644 libraries/ActionBarSherlock/AndroidManifest.xml create mode 100644 libraries/ActionBarSherlock/README.md create mode 100644 libraries/ActionBarSherlock/build.gradle create mode 100644 libraries/ActionBarSherlock/build.xml create mode 100644 libraries/ActionBarSherlock/libs/android-support-v4.jar create mode 100644 libraries/ActionBarSherlock/pom.xml create mode 100644 libraries/ActionBarSherlock/proguard-project.txt create mode 100644 libraries/ActionBarSherlock/project.properties create mode 100644 libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__ic_clear.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml create mode 100644 libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml create mode 100644 libraries/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml create mode 100644 libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_bar_home.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_bar_tab.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_menu_layout.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_mode_bar.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__screen_action_bar.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__screen_simple.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__search_view.xml create mode 100644 libraries/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml create mode 100644 libraries/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml create mode 100644 libraries/ActionBarSherlock/res/layout/sherlock_spinner_item.xml create mode 100644 libraries/ActionBarSherlock/res/values-land/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-large/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-sw600dp/abs__bools.xml create mode 100644 libraries/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-v11/abs__themes.xml create mode 100644 libraries/ActionBarSherlock/res/values-v14/abs__styles.xml create mode 100644 libraries/ActionBarSherlock/res/values-v14/abs__themes.xml create mode 100644 libraries/ActionBarSherlock/res/values-w360dp/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-w480dp/abs__bools.xml create mode 100644 libraries/ActionBarSherlock/res/values-w480dp/abs__config.xml create mode 100644 libraries/ActionBarSherlock/res/values-w500dp/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-w600dp/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values-xlarge/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__attrs.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__bools.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__colors.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__config.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__dimens.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__ids.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__strings.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__styles.xml create mode 100644 libraries/ActionBarSherlock/res/values/abs__themes.xml create mode 100644 libraries/ActionBarSherlock/src/android/support/v4/app/Watson.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java create mode 100644 libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java create mode 100644 libraries/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore index a1fa2dab4..71c11b159 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,30 @@ +#Android specific +bin +gen +obj +libs/armeabi +lint.xml +local.properties +release.properties +ant.properties *.class *.apk -.metadata \ No newline at end of file + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* + +#Eclipse +.project +.classpath +.settings +.metadata + +#IntelliJ IDEA +.idea +*.iml diff --git a/OpenPGP-Keychain-API-Demo/.gitignore b/OpenPGP-Keychain-API-Demo/.gitignore index 2e423e1a3..71c11b159 100644 --- a/OpenPGP-Keychain-API-Demo/.gitignore +++ b/OpenPGP-Keychain-API-Demo/.gitignore @@ -1,23 +1,30 @@ -#Android generated +#Android specific bin gen obj libs/armeabi lint.xml local.properties +release.properties +ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* #Eclipse .project .classpath .settings +.metadata #IntelliJ IDEA .idea *.iml - -#Maven -target -release.properties - -#Mac -.DS_Store \ No newline at end of file diff --git a/OpenPGP-Keychain-API-Lib/.gitignore b/OpenPGP-Keychain-API-Lib/.gitignore index 2e423e1a3..71c11b159 100644 --- a/OpenPGP-Keychain-API-Lib/.gitignore +++ b/OpenPGP-Keychain-API-Lib/.gitignore @@ -1,23 +1,30 @@ -#Android generated +#Android specific bin gen obj libs/armeabi lint.xml local.properties +release.properties +ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* #Eclipse .project .classpath .settings +.metadata #IntelliJ IDEA .idea *.iml - -#Maven -target -release.properties - -#Mac -.DS_Store \ No newline at end of file diff --git a/OpenPGP-Keychain/.gitignore b/OpenPGP-Keychain/.gitignore index 1eb5cbeae..71c11b159 100644 --- a/OpenPGP-Keychain/.gitignore +++ b/OpenPGP-Keychain/.gitignore @@ -1,24 +1,30 @@ -#Android generated +#Android specific bin gen obj libs/armeabi lint.xml local.properties +release.properties ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* #Eclipse .project .classpath .settings +.metadata #IntelliJ IDEA .idea *.iml - -#Maven -target -release.properties - -#Mac -.DS_Store \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/.gitignore b/OpenPGP-Keychain/android-libs/ActionBarSherlock/.gitignore deleted file mode 100644 index 2e423e1a3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -#Android generated -bin -gen -obj -libs/armeabi -lint.xml -local.properties - -#Eclipse -.project -.classpath -.settings - -#IntelliJ IDEA -.idea -*.iml - -#Maven -target -release.properties - -#Mac -.DS_Store \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/AndroidManifest.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/AndroidManifest.xml deleted file mode 100644 index 7b8a84824..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/AndroidManifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/README.md b/OpenPGP-Keychain/android-libs/ActionBarSherlock/README.md deleted file mode 100644 index e8a2c080e..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/README.md +++ /dev/null @@ -1,15 +0,0 @@ -ActionBarSherlock Library -========================= - -This folder contains the main library which should be linked against as an -Android library project in your application. - -For more information see the "Including In Your Project" section of the -[usage page][1]. - - - - - - - [1]: http://actionbarsherlock.com/usage.html diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/build.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/build.xml deleted file mode 100644 index a10a91491..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/build.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/libs/android-support-v4.jar b/OpenPGP-Keychain/android-libs/ActionBarSherlock/libs/android-support-v4.jar deleted file mode 100644 index 99e063b33..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/libs/android-support-v4.jar and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/pom.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/pom.xml deleted file mode 100644 index 3b6ce40ce..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/pom.xml +++ /dev/null @@ -1,148 +0,0 @@ - - - - 4.0.0 - - actionbarsherlock - ActionBarSherlock - apklib - - - com.actionbarsherlock - parent - 4.2.0 - ../pom.xml - - - - - com.google.android - android - provided - - - com.google.android - support-v4 - - - - junit - junit - test - - - - - src - test - - - - com.jayway.maven.plugins.android.generation2 - android-maven-plugin - true - - ignored - - - - - org.apache.maven.plugins - maven-javadoc-plugin - - true - - - - - com.google.code.maven-replacer-plugin - maven-replacer-plugin - 1.4.0 - - - process-sources - - replace - - - - - false - target/generated-sources/r/com/actionbarsherlock/R.java - target/generated-sources/r/com/actionbarsherlock/R.java - false - static final int - static int - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ../checkstyle.xml - - - - verify - - checkstyle - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - 1.7 - - - package - - attach-artifact - - - - - jar - ${project.build.directory}/${project.build.finalName}.jar - - - - - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - com.google.code.maven-replacer-plugin - maven-replacer-plugin - [1.4.0,) - - replace - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/proguard-project.txt b/OpenPGP-Keychain/android-libs/ActionBarSherlock/proguard-project.txt deleted file mode 100644 index f2fe1559a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/project.properties b/OpenPGP-Keychain/android-libs/ActionBarSherlock/project.properties deleted file mode 100644 index 5ca7d6247..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/project.properties +++ /dev/null @@ -1,12 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system use, -# "ant.properties", and override values to adapt the script to your -# project structure. - -android.library=true -# Project target. -target=android-14 diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml deleted file mode 100644 index ea7459aaf..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml deleted file mode 100644 index 0edb33b4b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml deleted file mode 100644 index 2bcfd0b63..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml deleted file mode 100644 index 198384fed..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png deleted file mode 100644 index 769463b36..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png deleted file mode 100644 index 88f11dcb9..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png deleted file mode 100644 index 73050476e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png deleted file mode 100644 index 712a551ec..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png deleted file mode 100644 index bf3b9438b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png deleted file mode 100644 index 81b87b86c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png deleted file mode 100644 index 8fc83e22e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png deleted file mode 100644 index cbbaec588..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png deleted file mode 100644 index af917e5b6..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png deleted file mode 100644 index 2d59f354e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png deleted file mode 100644 index 0520e5a2f..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png deleted file mode 100644 index e3e3f93b9..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png deleted file mode 100644 index 1e3957222..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png deleted file mode 100644 index a16db853e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png deleted file mode 100644 index 0eff695d8..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png deleted file mode 100644 index 219b170fa..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png deleted file mode 100644 index b0dc31fb3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png deleted file mode 100644 index 4bc2683b1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png deleted file mode 100644 index 4af38fb70..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png deleted file mode 100644 index d32f74cf4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png deleted file mode 100644 index 66adffed6..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png deleted file mode 100644 index caeff9c33..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png deleted file mode 100644 index 1d836f65a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png deleted file mode 100644 index 5818666d4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png deleted file mode 100644 index 564fb34b4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png deleted file mode 100644 index ae21b760f..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png deleted file mode 100644 index 79e56f522..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png deleted file mode 100644 index e029f210b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png deleted file mode 100644 index 897a1c11a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png deleted file mode 100644 index 0c89f7140..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png deleted file mode 100644 index d8662e3f0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png deleted file mode 100644 index ed03f620f..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png deleted file mode 100644 index d97c342d5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png deleted file mode 100644 index 33ad8d4b8..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png deleted file mode 100644 index 3edbd7408..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png deleted file mode 100644 index 90db01b5b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png deleted file mode 100644 index 97b825e83..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png deleted file mode 100644 index 7e1ba2adc..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png deleted file mode 100644 index 2abc45809..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png deleted file mode 100644 index bb6aef1d0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png deleted file mode 100644 index 6f747c8f0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png deleted file mode 100644 index 682b2fdec..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png deleted file mode 100644 index 4be72f108..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png deleted file mode 100644 index 72e207bc5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png deleted file mode 100644 index 66d14aec0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png deleted file mode 100644 index 3481c9828..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png deleted file mode 100644 index 4ea7afa00..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png deleted file mode 100644 index 986ab0b97..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png deleted file mode 100644 index 0279e17a1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png deleted file mode 100644 index 516f5c739..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png deleted file mode 100644 index 4ea7afa00..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png deleted file mode 100644 index 5654cd694..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png deleted file mode 100644 index 5654cd694..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png deleted file mode 100644 index f6fd30dcd..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png deleted file mode 100644 index ca8e9a277..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png deleted file mode 100644 index 4d3d20857..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png deleted file mode 100644 index 924a99d17..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png deleted file mode 100644 index 310c368e7..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png deleted file mode 100644 index 70cb7fc7e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png deleted file mode 100644 index 1c269205e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png deleted file mode 100644 index 1c269205e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png deleted file mode 100644 index 40d0d1645..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png deleted file mode 100644 index 40d0d1645..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png deleted file mode 100644 index c8358e9ce..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png deleted file mode 100644 index f62f74bb3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png deleted file mode 100644 index eb28ff9a5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png deleted file mode 100644 index d281adb55..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png deleted file mode 100644 index b29858609..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png deleted file mode 100644 index 4215396dd..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png deleted file mode 100644 index a280eabf5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png deleted file mode 100644 index f8d619b4d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png deleted file mode 100644 index 955a2f340..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png deleted file mode 100644 index 6c22e223a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png deleted file mode 100644 index 673e3bf10..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png deleted file mode 100644 index d57df98b5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png deleted file mode 100644 index 6278eef47..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png deleted file mode 100644 index aadc6f87b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png deleted file mode 100644 index 70c0e7396..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png deleted file mode 100644 index 36e71d85d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png deleted file mode 100644 index 4be4af5fa..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png deleted file mode 100644 index e72193f59..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png deleted file mode 100644 index 8f20b9d26..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png deleted file mode 100644 index 04f657e1d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png deleted file mode 100644 index 99309ef6d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png deleted file mode 100644 index 9bde7fbdc..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png deleted file mode 100644 index b2293670b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png deleted file mode 100644 index c65f443e3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png deleted file mode 100644 index 0706c8af6..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png deleted file mode 100644 index d814d02d3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png deleted file mode 100644 index b139c8e49..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png deleted file mode 100644 index 738cb38d0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png deleted file mode 100644 index 2ed75a767..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png deleted file mode 100644 index 743d00b6c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png deleted file mode 100644 index 17c1fb921..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png deleted file mode 100644 index ddfc8e3d5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png deleted file mode 100644 index 007a4b239..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png deleted file mode 100644 index ad6e1a4d9..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png deleted file mode 100644 index 0ad6c888b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png deleted file mode 100644 index 19b50abcb..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png deleted file mode 100644 index ad980b13f..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png deleted file mode 100644 index 60e6c5278..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png deleted file mode 100644 index 5461b9c00..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png deleted file mode 100644 index 5dc6f804a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png deleted file mode 100644 index a70b53c59..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png deleted file mode 100644 index c7a9896b0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png deleted file mode 100644 index 85d7aadd4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png deleted file mode 100644 index f7b01e012..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png deleted file mode 100644 index d8f1c8bd5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png deleted file mode 100644 index 31e49894a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png deleted file mode 100644 index 7c2cbe535..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png deleted file mode 100644 index 30cbdc174..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png deleted file mode 100644 index fb3660eab..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png deleted file mode 100644 index f18050ea5..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png deleted file mode 100644 index df2d3d158..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png deleted file mode 100644 index b2aa9c265..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png deleted file mode 100644 index a17b6a789..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png deleted file mode 100644 index b28b3b54f..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png deleted file mode 100644 index 79228baed..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png deleted file mode 100644 index 86944a879..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png deleted file mode 100644 index c0bdf0641..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png deleted file mode 100644 index 15b86cbb2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png deleted file mode 100644 index bf19833f2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png deleted file mode 100644 index 8518498eb..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png deleted file mode 100644 index ba704b67e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png deleted file mode 100644 index 01d681697..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png deleted file mode 100644 index 6bf21e307..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png deleted file mode 100644 index 70fe31aa2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png deleted file mode 100644 index 4be72f108..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png deleted file mode 100644 index f2e26f883..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png deleted file mode 100644 index 73c6be654..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png deleted file mode 100644 index 71d838e73..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png deleted file mode 100644 index 3bf8e0362..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png deleted file mode 100644 index 986ab0b97..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png deleted file mode 100644 index 0279e17a1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png deleted file mode 100644 index 7c0599e3a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png deleted file mode 100644 index 3bf8e0362..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png deleted file mode 100644 index 6e77525d2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png deleted file mode 100644 index 6e77525d2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png deleted file mode 100644 index 92da2f0dd..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png deleted file mode 100644 index 42cb6463e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png deleted file mode 100644 index 460ec46eb..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png deleted file mode 100644 index e84adf2d4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png deleted file mode 100644 index 3d946e545..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png deleted file mode 100644 index 4bb22f0e1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png deleted file mode 100644 index ab8ec6984..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png deleted file mode 100644 index ab8ec6984..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png deleted file mode 100644 index 7274274b1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png deleted file mode 100644 index 7274274b1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png deleted file mode 100644 index 9458668f0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png deleted file mode 100644 index 4ce73edce..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png deleted file mode 100644 index 29aff4d43..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png deleted file mode 100644 index 4055f7053..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png deleted file mode 100644 index ea4ee042e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png deleted file mode 100644 index f74c02b9e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png deleted file mode 100644 index 09a2992cc..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png deleted file mode 100644 index 6536ee633..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png deleted file mode 100644 index 202b5b72e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png deleted file mode 100644 index 6de0ba884..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png deleted file mode 100644 index c9972e74b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png deleted file mode 100644 index 587337caf..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png deleted file mode 100644 index 155c4fc75..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png deleted file mode 100644 index b1223fe3c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png deleted file mode 100644 index 081657ee7..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png deleted file mode 100644 index 3f312b465..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png deleted file mode 100644 index b086fae87..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png deleted file mode 100644 index 73c336a77..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png deleted file mode 100644 index 726e0ff42..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png deleted file mode 100644 index 726e0ff42..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png deleted file mode 100644 index 1767c169e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png deleted file mode 100644 index 1767c169e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml deleted file mode 100644 index 6bcbdb83f..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png deleted file mode 100644 index 575334699..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png deleted file mode 100644 index 7e6c047d6..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png deleted file mode 100644 index 8155fe840..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png deleted file mode 100644 index 6cee9a128..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png deleted file mode 100644 index fa4d76af9..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png deleted file mode 100644 index 9a70a5d1e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png deleted file mode 100644 index 14fbee101..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png deleted file mode 100644 index 6622cbad3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png deleted file mode 100644 index c42729783..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png deleted file mode 100644 index d0df29d8b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png deleted file mode 100644 index a0d9c1b95..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png deleted file mode 100644 index d36f99fec..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png deleted file mode 100644 index 5ad475dc3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png deleted file mode 100644 index 6ade5eeb3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png deleted file mode 100644 index 719b9234d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png deleted file mode 100644 index 6da264db2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png deleted file mode 100644 index 7ef2db75e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png deleted file mode 100644 index 2283b4c01..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png deleted file mode 100644 index 6d2039e28..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png deleted file mode 100644 index 3c909b513..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png deleted file mode 100644 index 131d1030c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png deleted file mode 100644 index 3e7dcdfdb..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png deleted file mode 100644 index 0bd09806f..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png deleted file mode 100644 index 43ed26d47..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png deleted file mode 100644 index 6b3157985..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png deleted file mode 100644 index df0121bb3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png deleted file mode 100644 index f4970ad1c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png deleted file mode 100644 index 172fc3b5e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png deleted file mode 100644 index 8ded62fb7..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png deleted file mode 100644 index 517e9f72d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png deleted file mode 100644 index 2e06dd01b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png deleted file mode 100644 index bb19810bc..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png deleted file mode 100644 index e35c5f05e..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png deleted file mode 100644 index 7fd7aeb2a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png deleted file mode 100644 index 53cfbd311..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png deleted file mode 100644 index 1e2dcfa02..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png deleted file mode 100644 index f12eafcdc..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png deleted file mode 100644 index a92fb1d4a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png deleted file mode 100644 index 930ca8d95..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png deleted file mode 100644 index 45a0f1da0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png deleted file mode 100644 index 528e554ab..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png deleted file mode 100644 index 998f91be9..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png deleted file mode 100644 index a4cdf1c79..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png deleted file mode 100644 index c625a3602..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png deleted file mode 100644 index c332ba08c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png deleted file mode 100644 index eda10e612..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png deleted file mode 100644 index e62f011d4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png deleted file mode 100644 index 65061c0f4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png deleted file mode 100644 index 690cb1eb6..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png deleted file mode 100644 index eda10e612..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png deleted file mode 100644 index e4b33935a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png deleted file mode 100644 index e4b33935a..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png deleted file mode 100644 index 88726b691..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png deleted file mode 100644 index c6a7d4d87..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png deleted file mode 100644 index e2aff72f4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png deleted file mode 100644 index 93066c840..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png deleted file mode 100644 index 345f5d306..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png deleted file mode 100644 index c843ef3af..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png deleted file mode 100644 index c6c3f1ec2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png deleted file mode 100644 index c6c3f1ec2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png deleted file mode 100644 index 205b66e2c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png deleted file mode 100644 index 205b66e2c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png deleted file mode 100644 index 19517c4b0..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png deleted file mode 100644 index 14143c51c..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png deleted file mode 100644 index d8929fcd1..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png deleted file mode 100644 index 9174c4e4b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png deleted file mode 100644 index 3015d3070..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png deleted file mode 100644 index 126637d11..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png deleted file mode 100644 index d45c7a864..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png deleted file mode 100644 index 29036b907..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png deleted file mode 100644 index 2cb34d7f6..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png deleted file mode 100644 index 82f752fdc..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png deleted file mode 100644 index 03cfb0945..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png deleted file mode 100644 index e4229f26b..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png deleted file mode 100644 index e862cb121..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png deleted file mode 100644 index f1eb67323..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png deleted file mode 100644 index 8fdbbf3ad..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png deleted file mode 100644 index 4e9ae43c2..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png deleted file mode 100644 index 98f4871bb..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png deleted file mode 100644 index 733373ed3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png deleted file mode 100644 index 0c6bb036d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png deleted file mode 100644 index 0c6bb036d..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png deleted file mode 100644 index e5bfd8ad3..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png deleted file mode 100644 index 1743da6b4..000000000 Binary files a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png and /dev/null differ diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml deleted file mode 100644 index 85c2c0212..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml deleted file mode 100644 index 85c2c0212..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml deleted file mode 100644 index cab896283..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml deleted file mode 100644 index 42ba8a0df..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml deleted file mode 100644 index a16f4b22e..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml deleted file mode 100644 index 256de80fb..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml deleted file mode 100644 index 2588a492d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml deleted file mode 100644 index e2078c967..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml deleted file mode 100644 index d99b7a426..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml deleted file mode 100644 index da5fb2e86..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml deleted file mode 100644 index b2ce4f0f7..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml deleted file mode 100644 index d7e31b1d1..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml deleted file mode 100644 index 08b8b12f3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml deleted file mode 100644 index ada490bf9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml deleted file mode 100644 index bd19140ab..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml deleted file mode 100644 index 321f07c8b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml deleted file mode 100644 index 6d4814f86..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml deleted file mode 100644 index 26284187a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml deleted file mode 100644 index 0d00c5878..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml deleted file mode 100644 index 4af5e22a9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml deleted file mode 100644 index b78508478..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml deleted file mode 100644 index d34e20811..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml deleted file mode 100644 index b6d58c040..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml deleted file mode 100644 index 3d6acf808..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml deleted file mode 100644 index 05ff4eda5..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml deleted file mode 100644 index f6d61e57a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml deleted file mode 100644 index 8811dad8d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml deleted file mode 100644 index 6c183c059..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml deleted file mode 100644 index 61dc02527..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml deleted file mode 100644 index 040df44ab..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml deleted file mode 100644 index c64ef141b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_home.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_home.xml deleted file mode 100644 index 5c1e9ec4b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_home.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab.xml deleted file mode 100644 index f46f7a044..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml deleted file mode 100644 index 0d51220c9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml deleted file mode 100644 index dd69acada..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml deleted file mode 100644 index 13149fd63..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_layout.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_layout.xml deleted file mode 100644 index a6f8e53f8..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_menu_layout.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_bar.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_bar.xml deleted file mode 100644 index 7168dc77f..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_bar.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml deleted file mode 100644 index 875ec3e1b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml deleted file mode 100644 index 6a0ac9ece..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml deleted file mode 100644 index b430032a1..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml deleted file mode 100644 index ab2b0ee6c..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml deleted file mode 100644 index 39aca3a8d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml deleted file mode 100644 index 55ab28a24..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml deleted file mode 100644 index 147f36fe8..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml deleted file mode 100644 index ff54bbecd..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml deleted file mode 100644 index d42425ad3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar.xml deleted file mode 100644 index 1fb82fe9a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml deleted file mode 100644 index 0961ef561..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple.xml deleted file mode 100644 index 33e2dea0d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml deleted file mode 100644 index f8b9fb185..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml deleted file mode 100644 index e1d3dc49c..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml deleted file mode 100644 index 6ba319121..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__search_view.xml +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml deleted file mode 100644 index 8fc0eb12c..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml deleted file mode 100644 index a6c6252d2..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_item.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_item.xml deleted file mode 100644 index bea740178..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/layout/sherlock_spinner_item.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-land/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-land/abs__dimens.xml deleted file mode 100644 index 502cc16a3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-land/abs__dimens.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 40dip - - 4dip - - 16dp - - 12dp - - -2dp - - 4dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml deleted file mode 100644 index 3312cfa7f..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 48dip - - 8dip - - 18dp - - 14dp - - -3dp - - 5dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml deleted file mode 100644 index 502cc16a3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 40dip - - 4dip - - 16dp - - 12dp - - -2dp - - 4dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml deleted file mode 100644 index 3312cfa7f..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 48dip - - 8dip - - 18dp - - 14dp - - -3dp - - 5dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml deleted file mode 100644 index 35910333b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - 56dip - - 4dip - - 18dp - - 14dp - - -3dp - - 9dip - - - 64dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large/abs__dimens.xml deleted file mode 100644 index 63b12f7f3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-large/abs__dimens.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - 55% - - 80% - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__bools.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__bools.xml deleted file mode 100644 index 7a48e1542..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__bools.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - false - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml deleted file mode 100644 index f67853817..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - 56dip - - 4dip - - 18dp - - 14dp - - -3dp - - 9dip - - 5 - - - 64dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v11/abs__themes.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v11/abs__themes.xml deleted file mode 100644 index 03473572c..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v11/abs__themes.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml deleted file mode 100644 index 88a60dd92..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__styles.xml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml deleted file mode 100644 index 5fac1ab58..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-v14/abs__themes.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w360dp/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w360dp/abs__dimens.xml deleted file mode 100644 index 6f49d7e47..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w360dp/abs__dimens.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 3 - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__bools.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__bools.xml deleted file mode 100644 index 3eaf4aee9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__bools.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - true - false - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__config.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__config.xml deleted file mode 100644 index 88357b0a7..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w480dp/abs__config.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - true - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w500dp/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w500dp/abs__dimens.xml deleted file mode 100644 index 2fd4deea2..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w500dp/abs__dimens.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 4 - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w600dp/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w600dp/abs__dimens.xml deleted file mode 100644 index b085952d3..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-w600dp/abs__dimens.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 5 - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-xlarge/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-xlarge/abs__dimens.xml deleted file mode 100644 index bfc535de1..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values-xlarge/abs__dimens.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - 56dip - - 4dip - - 18dp - - 14dp - - -3dp - - 9dip - - - 64dip - - - 45% - - 72% - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__attrs.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__attrs.xml deleted file mode 100644 index 32631ca8d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__attrs.xml +++ /dev/null @@ -1,432 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__bools.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__bools.xml deleted file mode 100644 index 0b432448d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__bools.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - false - true - true - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__colors.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__colors.xml deleted file mode 100644 index 625c632ff..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__colors.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - #ff000000 - #fff3f3f3 - @color/abs__background_holo_light - @color/abs__background_holo_dark - #ff4c4c4c - #ffb2b2b2 - @color/abs__bright_foreground_holo_light - @color/abs__bright_foreground_holo_dark - #ff33b5e5 - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__config.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__config.xml deleted file mode 100644 index 4c7b5d459..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__config.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - 320dp - - - false - - - true - - - false - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__dimens.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__dimens.xml deleted file mode 100644 index 831289e07..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__dimens.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - 48dip - - 8dip - - 18dp - - 14dp - - -3dp - - 5dip - - 2 - - - 56dip - - - 64dip - - - 65% - - 95% - - - - 8dip - - - 8dip - - - 32dip - - - - 160dip - - - 320dip - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__ids.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__ids.xml deleted file mode 100644 index f9f56045b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__ids.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__strings.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__strings.xml deleted file mode 100644 index 06a2a2af4..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__strings.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Navigate home - - Navigate up - - More options - - - Done - - - See all... - - Select activity - - Share with... - - Choose an application - - Share with - - Share with %s - - - Search - - Search query - - Clear query - - Submit query - - Voice search - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__styles.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__styles.xml deleted file mode 100644 index 45a18c183..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__styles.xml +++ /dev/null @@ -1,412 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__themes.xml b/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__themes.xml deleted file mode 100644 index 634fa798b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/res/values/abs__themes.xml +++ /dev/null @@ -1,239 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java deleted file mode 100644 index d93de4c6a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/android/support/v4/app/Watson.java +++ /dev/null @@ -1,144 +0,0 @@ -package android.support.v4.app; - -import android.util.Log; -import android.view.View; -import android.view.Window; -import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; -import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; -import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -import java.util.ArrayList; - -/** I'm in ur package. Stealing ur variables. */ -public abstract class Watson extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener { - private static final boolean DEBUG = false; - private static final String TAG = "Watson"; - - /** Fragment interface for menu creation callback. */ - public interface OnCreateOptionsMenuListener { - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater); - } - /** Fragment interface for menu preparation callback. */ - public interface OnPrepareOptionsMenuListener { - public void onPrepareOptionsMenu(Menu menu); - } - /** Fragment interface for menu item selection callback. */ - public interface OnOptionsItemSelectedListener { - public boolean onOptionsItemSelected(MenuItem item); - } - - private ArrayList mCreatedMenus; - - - /////////////////////////////////////////////////////////////////////////// - // Sherlock menu handling - /////////////////////////////////////////////////////////////////////////// - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] featureId: " + featureId + ", menu: " + menu); - - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - boolean result = onCreateOptionsMenu(menu); - if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] activity create result: " + result); - - MenuInflater inflater = getSupportMenuInflater(); - boolean show = false; - ArrayList newMenus = null; - if (mFragments.mAdded != null) { - for (int i = 0; i < mFragments.mAdded.size(); i++) { - Fragment f = mFragments.mAdded.get(i); - if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnCreateOptionsMenuListener) { - show = true; - ((OnCreateOptionsMenuListener)f).onCreateOptionsMenu(menu, inflater); - if (newMenus == null) { - newMenus = new ArrayList(); - } - newMenus.add(f); - } - } - } - - if (mCreatedMenus != null) { - for (int i = 0; i < mCreatedMenus.size(); i++) { - Fragment f = mCreatedMenus.get(i); - if (newMenus == null || !newMenus.contains(f)) { - f.onDestroyOptionsMenu(); - } - } - } - - mCreatedMenus = newMenus; - - if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] fragments create result: " + show); - result |= show; - - if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] returning " + result); - return result; - } - return false; - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (DEBUG) Log.d(TAG, "[onPreparePanel] featureId: " + featureId + ", view: " + view + " menu: " + menu); - - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - boolean result = onPrepareOptionsMenu(menu); - if (DEBUG) Log.d(TAG, "[onPreparePanel] activity prepare result: " + result); - - boolean show = false; - if (mFragments.mAdded != null) { - for (int i = 0; i < mFragments.mAdded.size(); i++) { - Fragment f = mFragments.mAdded.get(i); - if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnPrepareOptionsMenuListener) { - show = true; - ((OnPrepareOptionsMenuListener)f).onPrepareOptionsMenu(menu); - } - } - } - - if (DEBUG) Log.d(TAG, "[onPreparePanel] fragments prepare result: " + show); - result |= show; - - result &= menu.hasVisibleItems(); - if (DEBUG) Log.d(TAG, "[onPreparePanel] returning " + result); - return result; - } - return false; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (DEBUG) Log.d(TAG, "[onMenuItemSelected] featureId: " + featureId + ", item: " + item); - - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - if (onOptionsItemSelected(item)) { - return true; - } - - if (mFragments.mAdded != null) { - for (int i = 0; i < mFragments.mAdded.size(); i++) { - Fragment f = mFragments.mAdded.get(i); - if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnOptionsItemSelectedListener) { - if (((OnOptionsItemSelectedListener)f).onOptionsItemSelected(item)) { - return true; - } - } - } - } - } - return false; - } - - public abstract boolean onCreateOptionsMenu(Menu menu); - - public abstract boolean onPrepareOptionsMenu(Menu menu); - - public abstract boolean onOptionsItemSelected(MenuItem item); - - public abstract MenuInflater getSupportMenuInflater(); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java deleted file mode 100644 index ab160f836..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java +++ /dev/null @@ -1,794 +0,0 @@ -package com.actionbarsherlock; - -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Iterator; -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.internal.ActionBarSherlockCompat; -import com.actionbarsherlock.internal.ActionBarSherlockNative; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -/** - *

Helper for implementing the action bar design pattern across all versions - * of Android.

- * - *

This class will manage interaction with a custom action bar based on the - * Android 4.0 source code. The exposed API mirrors that of its native - * counterpart and you should refer to its documentation for instruction.

- * - * @author Jake Wharton - */ -public abstract class ActionBarSherlock { - protected static final String TAG = "ActionBarSherlock"; - protected static final boolean DEBUG = false; - - private static final Class[] CONSTRUCTOR_ARGS = new Class[] { Activity.class, int.class }; - private static final HashMap> IMPLEMENTATIONS = - new HashMap>(); - - static { - //Register our two built-in implementations - registerImplementation(ActionBarSherlockCompat.class); - registerImplementation(ActionBarSherlockNative.class); - } - - - /** - *

Denotes an implementation of ActionBarSherlock which provides an - * action bar-enhanced experience.

- */ - @Target(ElementType.TYPE) - @Retention(RetentionPolicy.RUNTIME) - public @interface Implementation { - static final int DEFAULT_API = -1; - static final int DEFAULT_DPI = -1; - - int api() default DEFAULT_API; - int dpi() default DEFAULT_DPI; - } - - - /** Activity interface for menu creation callback. */ - public interface OnCreatePanelMenuListener { - public boolean onCreatePanelMenu(int featureId, Menu menu); - } - /** Activity interface for menu creation callback. */ - public interface OnCreateOptionsMenuListener { - public boolean onCreateOptionsMenu(Menu menu); - } - /** Activity interface for menu item selection callback. */ - public interface OnMenuItemSelectedListener { - public boolean onMenuItemSelected(int featureId, MenuItem item); - } - /** Activity interface for menu item selection callback. */ - public interface OnOptionsItemSelectedListener { - public boolean onOptionsItemSelected(MenuItem item); - } - /** Activity interface for menu preparation callback. */ - public interface OnPreparePanelListener { - public boolean onPreparePanel(int featureId, View view, Menu menu); - } - /** Activity interface for menu preparation callback. */ - public interface OnPrepareOptionsMenuListener { - public boolean onPrepareOptionsMenu(Menu menu); - } - /** Activity interface for action mode finished callback. */ - public interface OnActionModeFinishedListener { - public void onActionModeFinished(ActionMode mode); - } - /** Activity interface for action mode started callback. */ - public interface OnActionModeStartedListener { - public void onActionModeStarted(ActionMode mode); - } - - - /** - * If set, the logic in these classes will assume that an {@link Activity} - * is dispatching all of the required events to the class. This flag should - * only be used internally or if you are creating your own base activity - * modeled after one of the included types (e.g., {@code SherlockActivity}). - */ - public static final int FLAG_DELEGATE = 1; - - - /** - * Register an ActionBarSherlock implementation. - * - * @param implementationClass Target implementation class which extends - * {@link ActionBarSherlock}. This class must also be annotated with - * {@link Implementation}. - */ - public static void registerImplementation(Class implementationClass) { - if (!implementationClass.isAnnotationPresent(Implementation.class)) { - throw new IllegalArgumentException("Class " + implementationClass.getSimpleName() + " is not annotated with @Implementation"); - } else if (IMPLEMENTATIONS.containsValue(implementationClass)) { - if (DEBUG) Log.w(TAG, "Class " + implementationClass.getSimpleName() + " already registered"); - return; - } - - Implementation impl = implementationClass.getAnnotation(Implementation.class); - if (DEBUG) Log.i(TAG, "Registering " + implementationClass.getSimpleName() + " with qualifier " + impl); - IMPLEMENTATIONS.put(impl, implementationClass); - } - - /** - * Unregister an ActionBarSherlock implementation. This should be - * considered very volatile and you should only use it if you know what - * you are doing. You have been warned. - * - * @param implementationClass Target implementation class. - * @return Boolean indicating whether the class was removed. - */ - public static boolean unregisterImplementation(Class implementationClass) { - return IMPLEMENTATIONS.values().remove(implementationClass); - } - - /** - * Wrap an activity with an action bar abstraction which will enable the - * use of a custom implementation on platforms where a native version does - * not exist. - * - * @param activity Activity to wrap. - * @return Instance to interact with the action bar. - */ - public static ActionBarSherlock wrap(Activity activity) { - return wrap(activity, 0); - } - - /** - * Wrap an activity with an action bar abstraction which will enable the - * use of a custom implementation on platforms where a native version does - * not exist. - * - * @param activity Owning activity. - * @param flags Option flags to control behavior. - * @return Instance to interact with the action bar. - */ - public static ActionBarSherlock wrap(Activity activity, int flags) { - //Create a local implementation map we can modify - HashMap> impls = - new HashMap>(IMPLEMENTATIONS); - boolean hasQualfier; - - /* DPI FILTERING */ - hasQualfier = false; - for (Implementation key : impls.keySet()) { - //Only honor TVDPI as a specific qualifier - if (key.dpi() == DisplayMetrics.DENSITY_TV) { - hasQualfier = true; - break; - } - } - if (hasQualfier) { - final boolean isTvDpi = activity.getResources().getDisplayMetrics().densityDpi == DisplayMetrics.DENSITY_TV; - for (Iterator keys = impls.keySet().iterator(); keys.hasNext(); ) { - int keyDpi = keys.next().dpi(); - if ((isTvDpi && keyDpi != DisplayMetrics.DENSITY_TV) - || (!isTvDpi && keyDpi == DisplayMetrics.DENSITY_TV)) { - keys.remove(); - } - } - } - - /* API FILTERING */ - hasQualfier = false; - for (Implementation key : impls.keySet()) { - if (key.api() != Implementation.DEFAULT_API) { - hasQualfier = true; - break; - } - } - if (hasQualfier) { - final int runtimeApi = Build.VERSION.SDK_INT; - int bestApi = 0; - for (Iterator keys = impls.keySet().iterator(); keys.hasNext(); ) { - int keyApi = keys.next().api(); - if (keyApi > runtimeApi) { - keys.remove(); - } else if (keyApi > bestApi) { - bestApi = keyApi; - } - } - for (Iterator keys = impls.keySet().iterator(); keys.hasNext(); ) { - if (keys.next().api() != bestApi) { - keys.remove(); - } - } - } - - if (impls.size() > 1) { - throw new IllegalStateException("More than one implementation matches configuration."); - } - if (impls.isEmpty()) { - throw new IllegalStateException("No implementations match configuration."); - } - Class impl = impls.values().iterator().next(); - if (DEBUG) Log.i(TAG, "Using implementation: " + impl.getSimpleName()); - - try { - Constructor ctor = impl.getConstructor(CONSTRUCTOR_ARGS); - return ctor.newInstance(activity, flags); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - } - - - /** Activity which is displaying the action bar. Also used for context. */ - protected final Activity mActivity; - /** Whether delegating actions for the activity or managing ourselves. */ - protected final boolean mIsDelegate; - - /** Reference to our custom menu inflater which supports action items. */ - protected MenuInflater mMenuInflater; - - - - protected ActionBarSherlock(Activity activity, int flags) { - if (DEBUG) Log.d(TAG, "[] activity: " + activity + ", flags: " + flags); - - mActivity = activity; - mIsDelegate = (flags & FLAG_DELEGATE) != 0; - } - - - /** - * Get the current action bar instance. - * - * @return Action bar instance. - */ - public abstract ActionBar getActionBar(); - - - /////////////////////////////////////////////////////////////////////////// - // Lifecycle and interaction callbacks when delegating - /////////////////////////////////////////////////////////////////////////// - - /** - * Notify action bar of a configuration change event. Should be dispatched - * after the call to the superclass implementation. - * - *
-     * @Override
-     * public void onConfigurationChanged(Configuration newConfig) {
-     *     super.onConfigurationChanged(newConfig);
-     *     mSherlock.dispatchConfigurationChanged(newConfig);
-     * }
-     * 
- * - * @param newConfig The new device configuration. - */ - public void dispatchConfigurationChanged(Configuration newConfig) {} - - /** - * Notify the action bar that the activity has finished its resuming. This - * should be dispatched after the call to the superclass implementation. - * - *
-     * @Override
-     * protected void onPostResume() {
-     *     super.onPostResume();
-     *     mSherlock.dispatchPostResume();
-     * }
-     * 
- */ - public void dispatchPostResume() {} - - /** - * Notify the action bar that the activity is pausing. This should be - * dispatched before the call to the superclass implementation. - * - *
-     * @Override
-     * protected void onPause() {
-     *     mSherlock.dispatchPause();
-     *     super.onPause();
-     * }
-     * 
- */ - public void dispatchPause() {} - - /** - * Notify the action bar that the activity is stopping. This should be - * called before the superclass implementation. - * - *

- * @Override - * protected void onStop() { - * mSherlock.dispatchStop(); - * super.onStop(); - * } - *

- */ - public void dispatchStop() {} - - /** - * Indicate that the menu should be recreated by calling - * {@link OnCreateOptionsMenuListener#onCreateOptionsMenu(com.actionbarsherlock.view.Menu)}. - */ - public abstract void dispatchInvalidateOptionsMenu(); - - /** - * Notify the action bar that it should display its overflow menu if it is - * appropriate for the device. The implementation should conditionally - * call the superclass method only if this method returns {@code false}. - * - *

- * @Override - * public void openOptionsMenu() { - * if (!mSherlock.dispatchOpenOptionsMenu()) { - * super.openOptionsMenu(); - * } - * } - *

- * - * @return {@code true} if the opening of the menu was handled internally. - */ - public boolean dispatchOpenOptionsMenu() { - return false; - } - - /** - * Notify the action bar that it should close its overflow menu if it is - * appropriate for the device. This implementation should conditionally - * call the superclass method only if this method returns {@code false}. - * - *
-     * @Override
-     * public void closeOptionsMenu() {
-     *     if (!mSherlock.dispatchCloseOptionsMenu()) {
-     *         super.closeOptionsMenu();
-     *     }
-     * }
-     * 
- * - * @return {@code true} if the closing of the menu was handled internally. - */ - public boolean dispatchCloseOptionsMenu() { - return false; - } - - /** - * Notify the class that the activity has finished its creation. This - * should be called after the superclass implementation. - * - *
-     * @Override
-     * protected void onPostCreate(Bundle savedInstanceState) {
-     *     mSherlock.dispatchPostCreate(savedInstanceState);
-     *     super.onPostCreate(savedInstanceState);
-     * }
-     * 
- * - * @param savedInstanceState If the activity is being re-initialized after - * previously being shut down then this Bundle - * contains the data it most recently supplied in - * {@link Activity#}onSaveInstanceState(Bundle)}. - * Note: Otherwise it is null. - */ - public void dispatchPostCreate(Bundle savedInstanceState) {} - - /** - * Notify the action bar that the title has changed and the action bar - * should be updated to reflect the change. This should be called before - * the superclass implementation. - * - *
-     *  @Override
-     *  protected void onTitleChanged(CharSequence title, int color) {
-     *      mSherlock.dispatchTitleChanged(title, color);
-     *      super.onTitleChanged(title, color);
-     *  }
-     * 
- * - * @param title New activity title. - * @param color New activity color. - */ - public void dispatchTitleChanged(CharSequence title, int color) {} - - /** - * Notify the action bar the user has created a key event. This is used to - * toggle the display of the overflow action item with the menu key and to - * close the action mode or expanded action item with the back key. - * - *
-     * @Override
-     * public boolean dispatchKeyEvent(KeyEvent event) {
-     *     if (mSherlock.dispatchKeyEvent(event)) {
-     *         return true;
-     *     }
-     *     return super.dispatchKeyEvent(event);
-     * }
-     * 
- * - * @param event Description of the key event. - * @return {@code true} if the event was handled. - */ - public boolean dispatchKeyEvent(KeyEvent event) { - return false; - } - - /** - * Notify the action bar that the Activity has triggered a menu creation - * which should happen on the conclusion of {@link Activity#onCreate}. This - * will be used to gain a reference to the native menu for native and - * overflow binding as well as to indicate when compatibility create should - * occur for the first time. - * - * @param menu Activity native menu. - * @return {@code true} since we always want to say that we have a native - */ - public abstract boolean dispatchCreateOptionsMenu(android.view.Menu menu); - - /** - * Notify the action bar that the Activity has triggered a menu preparation - * which usually means that the user has requested the overflow menu via a - * hardware menu key. You should return the result of this method call and - * not call the superclass implementation. - * - *

- * @Override - * public final boolean onPrepareOptionsMenu(android.view.Menu menu) { - * return mSherlock.dispatchPrepareOptionsMenu(menu); - * } - *

- * - * @param menu Activity native menu. - * @return {@code true} if menu display should proceed. - */ - public abstract boolean dispatchPrepareOptionsMenu(android.view.Menu menu); - - /** - * Notify the action bar that a native options menu item has been selected. - * The implementation should return the result of this method call. - * - *

- * @Override - * public final boolean onOptionsItemSelected(android.view.MenuItem item) { - * return mSherlock.dispatchOptionsItemSelected(item); - * } - *

- * - * @param item Options menu item. - * @return @{code true} if the selection was handled. - */ - public abstract boolean dispatchOptionsItemSelected(android.view.MenuItem item); - - /** - * Notify the action bar that the overflow menu has been opened. The - * implementation should conditionally return {@code true} if this method - * returns {@code true}, otherwise return the result of the superclass - * method. - * - *

- * @Override - * public final boolean onMenuOpened(int featureId, android.view.Menu menu) { - * if (mSherlock.dispatchMenuOpened(featureId, menu)) { - * return true; - * } - * return super.onMenuOpened(featureId, menu); - * } - *

- * - * @param featureId Window feature which triggered the event. - * @param menu Activity native menu. - * @return {@code true} if the event was handled by this method. - */ - public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) { - return false; - } - - /** - * Notify the action bar that the overflow menu has been closed. This - * method should be called before the superclass implementation. - * - *

- * @Override - * public void onPanelClosed(int featureId, android.view.Menu menu) { - * mSherlock.dispatchPanelClosed(featureId, menu); - * super.onPanelClosed(featureId, menu); - * } - *

- * - * @param featureId - * @param menu - */ - public void dispatchPanelClosed(int featureId, android.view.Menu menu) {} - - /** - * Notify the action bar that the activity has been destroyed. This method - * should be called before the superclass implementation. - * - *

- * @Override - * public void onDestroy() { - * mSherlock.dispatchDestroy(); - * super.onDestroy(); - * } - *

- */ - public void dispatchDestroy() {} - - public void dispatchSaveInstanceState(Bundle outState) {} - - public void dispatchRestoreInstanceState(Bundle savedInstanceState) {} - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - - /** - * Internal method to trigger the menu creation process. - * - * @return {@code true} if menu creation should proceed. - */ - protected final boolean callbackCreateOptionsMenu(Menu menu) { - if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] menu: " + menu); - - boolean result = true; - if (mActivity instanceof OnCreatePanelMenuListener) { - OnCreatePanelMenuListener listener = (OnCreatePanelMenuListener)mActivity; - result = listener.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu); - } else if (mActivity instanceof OnCreateOptionsMenuListener) { - OnCreateOptionsMenuListener listener = (OnCreateOptionsMenuListener)mActivity; - result = listener.onCreateOptionsMenu(menu); - } - - if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] returning " + result); - return result; - } - - /** - * Internal method to trigger the menu preparation process. - * - * @return {@code true} if menu preparation should proceed. - */ - protected final boolean callbackPrepareOptionsMenu(Menu menu) { - if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] menu: " + menu); - - boolean result = true; - if (mActivity instanceof OnPreparePanelListener) { - OnPreparePanelListener listener = (OnPreparePanelListener)mActivity; - result = listener.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu); - } else if (mActivity instanceof OnPrepareOptionsMenuListener) { - OnPrepareOptionsMenuListener listener = (OnPrepareOptionsMenuListener)mActivity; - result = listener.onPrepareOptionsMenu(menu); - } - - if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] returning " + result); - return result; - } - - /** - * Internal method for dispatching options menu selection to the owning - * activity callback. - * - * @param item Selected options menu item. - * @return {@code true} if the item selection was handled in the callback. - */ - protected final boolean callbackOptionsItemSelected(MenuItem item) { - if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] item: " + item.getTitleCondensed()); - - boolean result = false; - if (mActivity instanceof OnMenuItemSelectedListener) { - OnMenuItemSelectedListener listener = (OnMenuItemSelectedListener)mActivity; - result = listener.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); - } else if (mActivity instanceof OnOptionsItemSelectedListener) { - OnOptionsItemSelectedListener listener = (OnOptionsItemSelectedListener)mActivity; - result = listener.onOptionsItemSelected(item); - } - - if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] returning " + result); - return result; - } - - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - - /** - * Query for the availability of a certain feature. - * - * @param featureId The feature ID to check. - * @return {@code true} if feature is enabled, {@code false} otherwise. - */ - public abstract boolean hasFeature(int featureId); - - /** - * Enable extended screen features. This must be called before - * {@code setContentView()}. May be called as many times as desired as long - * as it is before {@code setContentView()}. If not called, no extended - * features will be available. You can not turn off a feature once it is - * requested. - * - * @param featureId The desired features, defined as constants by Window. - * @return Returns true if the requested feature is supported and now - * enabled. - */ - public abstract boolean requestFeature(int featureId); - - /** - * Set extra options that will influence the UI for this window. - * - * @param uiOptions Flags specifying extra options for this window. - */ - public abstract void setUiOptions(int uiOptions); - - /** - * Set extra options that will influence the UI for this window. Only the - * bits filtered by mask will be modified. - * - * @param uiOptions Flags specifying extra options for this window. - * @param mask Flags specifying which options should be modified. Others - * will remain unchanged. - */ - public abstract void setUiOptions(int uiOptions, int mask); - - /** - * Set the content of the activity inside the action bar. - * - * @param layoutResId Layout resource ID. - */ - public abstract void setContentView(int layoutResId); - - /** - * Set the content of the activity inside the action bar. - * - * @param view The desired content to display. - */ - public void setContentView(View view) { - if (DEBUG) Log.d(TAG, "[setContentView] view: " + view); - - setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); - } - - /** - * Set the content of the activity inside the action bar. - * - * @param view The desired content to display. - * @param params Layout parameters to apply to the view. - */ - public abstract void setContentView(View view, ViewGroup.LayoutParams params); - - /** - * Variation on {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)} - * to add an additional content view to the screen. Added after any - * existing ones on the screen -- existing views are NOT removed. - * - * @param view The desired content to display. - * @param params Layout parameters for the view. - */ - public abstract void addContentView(View view, ViewGroup.LayoutParams params); - - /** - * Change the title associated with this activity. - */ - public abstract void setTitle(CharSequence title); - - /** - * Change the title associated with this activity. - */ - public void setTitle(int resId) { - if (DEBUG) Log.d(TAG, "[setTitle] resId: " + resId); - - setTitle(mActivity.getString(resId)); - } - - /** - * Sets the visibility of the progress bar in the title. - *

- * In order for the progress bar to be shown, the feature must be requested - * via {@link #requestWindowFeature(int)}. - * - * @param visible Whether to show the progress bars in the title. - */ - public abstract void setProgressBarVisibility(boolean visible); - - /** - * Sets the visibility of the indeterminate progress bar in the title. - *

- * In order for the progress bar to be shown, the feature must be requested - * via {@link #requestWindowFeature(int)}. - * - * @param visible Whether to show the progress bars in the title. - */ - public abstract void setProgressBarIndeterminateVisibility(boolean visible); - - /** - * Sets whether the horizontal progress bar in the title should be indeterminate (the circular - * is always indeterminate). - *

- * In order for the progress bar to be shown, the feature must be requested - * via {@link #requestWindowFeature(int)}. - * - * @param indeterminate Whether the horizontal progress bar should be indeterminate. - */ - public abstract void setProgressBarIndeterminate(boolean indeterminate); - - /** - * Sets the progress for the progress bars in the title. - *

- * In order for the progress bar to be shown, the feature must be requested - * via {@link #requestWindowFeature(int)}. - * - * @param progress The progress for the progress bar. Valid ranges are from - * 0 to 10000 (both inclusive). If 10000 is given, the progress - * bar will be completely filled and will fade out. - */ - public abstract void setProgress(int progress); - - /** - * Sets the secondary progress for the progress bar in the title. This - * progress is drawn between the primary progress (set via - * {@link #setProgress(int)} and the background. It can be ideal for media - * scenarios such as showing the buffering progress while the default - * progress shows the play progress. - *

- * In order for the progress bar to be shown, the feature must be requested - * via {@link #requestWindowFeature(int)}. - * - * @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from - * 0 to 10000 (both inclusive). - */ - public abstract void setSecondaryProgress(int secondaryProgress); - - /** - * Get a menu inflater instance which supports the newer menu attributes. - * - * @return Menu inflater instance. - */ - public MenuInflater getMenuInflater() { - if (DEBUG) Log.d(TAG, "[getMenuInflater]"); - - // Make sure that action views can get an appropriate theme. - if (mMenuInflater == null) { - if (getActionBar() != null) { - mMenuInflater = new MenuInflater(getThemedContext(), mActivity); - } else { - mMenuInflater = new MenuInflater(mActivity); - } - } - return mMenuInflater; - } - - protected abstract Context getThemedContext(); - - /** - * Start an action mode. - * - * @param callback Callback that will manage lifecycle events for this - * context mode. - * @return The ContextMode that was started, or null if it was canceled. - * @see ActionMode - */ - public abstract ActionMode startActionMode(ActionMode.Callback callback); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java deleted file mode 100644 index 03755be2b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java +++ /dev/null @@ -1,956 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.app; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.support.v4.app.FragmentTransaction; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewDebug; -import android.view.ViewGroup; -import android.view.ViewGroup.MarginLayoutParams; -import android.widget.SpinnerAdapter; - -/** - * A window feature at the top of the activity that may display the activity title, navigation - * modes, and other interactive items. - *

Beginning with Android 3.0 (API level 11), the action bar appears at the top of an - * activity's window when the activity uses the system's {@link - * android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default. - * You may otherwise add the action bar by calling {@link - * android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a - * custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property. - *

By default, the action bar shows the application icon on - * the left, followed by the activity title. If your activity has an options menu, you can make - * select items accessible directly from the action bar as "action items". You can also - * modify various characteristics of the action bar or remove it completely.

- *

From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link - * android.app.Activity#getActionBar getActionBar()}.

- *

In some cases, the action bar may be overlayed by another bar that enables contextual actions, - * using an {@link android.view.ActionMode}. For example, when the user selects one or more items in - * your activity, you can enable an action mode that offers actions specific to the selected - * items, with a UI that temporarily replaces the action bar. Although the UI may occupy the - * same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for - * {@link ActionBar}. - *

- *

Developer Guides

- *

For information about how to use the action bar, including how to add action items, navigation - * modes and more, read the Action - * Bar developer guide.

- *
- */ -public abstract class ActionBar { - /** - * Standard navigation mode. Consists of either a logo or icon - * and title text with an optional subtitle. Clicking any of these elements - * will dispatch onOptionsItemSelected to the host Activity with - * a MenuItem with item ID android.R.id.home. - */ - public static final int NAVIGATION_MODE_STANDARD = android.app.ActionBar.NAVIGATION_MODE_STANDARD; - - /** - * List navigation mode. Instead of static title text this mode - * presents a list menu for navigation within the activity. - * e.g. this might be presented to the user as a dropdown list. - */ - public static final int NAVIGATION_MODE_LIST = android.app.ActionBar.NAVIGATION_MODE_LIST; - - /** - * Tab navigation mode. Instead of static title text this mode - * presents a series of tabs for navigation within the activity. - */ - public static final int NAVIGATION_MODE_TABS = android.app.ActionBar.NAVIGATION_MODE_TABS; - - /** - * Use logo instead of icon if available. This flag will cause appropriate - * navigation modes to use a wider logo in place of the standard icon. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public static final int DISPLAY_USE_LOGO = android.app.ActionBar.DISPLAY_USE_LOGO; - - /** - * Show 'home' elements in this action bar, leaving more space for other - * navigation elements. This includes logo and icon. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public static final int DISPLAY_SHOW_HOME = android.app.ActionBar.DISPLAY_SHOW_HOME; - - /** - * Display the 'home' element such that it appears as an 'up' affordance. - * e.g. show an arrow to the left indicating the action that will be taken. - * - * Set this flag if selecting the 'home' button in the action bar to return - * up by a single level in your UI rather than back to the top level or front page. - * - *

Setting this option will implicitly enable interaction with the home/up - * button. See {@link #setHomeButtonEnabled(boolean)}. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public static final int DISPLAY_HOME_AS_UP = android.app.ActionBar.DISPLAY_HOME_AS_UP; - - /** - * Show the activity title and subtitle, if present. - * - * @see #setTitle(CharSequence) - * @see #setTitle(int) - * @see #setSubtitle(CharSequence) - * @see #setSubtitle(int) - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public static final int DISPLAY_SHOW_TITLE = android.app.ActionBar.DISPLAY_SHOW_TITLE; - - /** - * Show the custom view if one has been set. - * @see #setCustomView(View) - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public static final int DISPLAY_SHOW_CUSTOM = android.app.ActionBar.DISPLAY_SHOW_CUSTOM; - - /** - * Set the action bar into custom navigation mode, supplying a view - * for custom navigation. - * - * Custom navigation views appear between the application icon and - * any action buttons and may use any space available there. Common - * use cases for custom navigation views might include an auto-suggesting - * address bar for a browser or other navigation mechanisms that do not - * translate well to provided navigation modes. - * - * @param view Custom navigation view to place in the ActionBar. - */ - public abstract void setCustomView(View view); - - /** - * Set the action bar into custom navigation mode, supplying a view - * for custom navigation. - * - *

Custom navigation views appear between the application icon and - * any action buttons and may use any space available there. Common - * use cases for custom navigation views might include an auto-suggesting - * address bar for a browser or other navigation mechanisms that do not - * translate well to provided navigation modes.

- * - *

The display option {@link #DISPLAY_SHOW_CUSTOM} must be set for - * the custom view to be displayed.

- * - * @param view Custom navigation view to place in the ActionBar. - * @param layoutParams How this custom view should layout in the bar. - * - * @see #setDisplayOptions(int, int) - */ - public abstract void setCustomView(View view, LayoutParams layoutParams); - - /** - * Set the action bar into custom navigation mode, supplying a view - * for custom navigation. - * - *

Custom navigation views appear between the application icon and - * any action buttons and may use any space available there. Common - * use cases for custom navigation views might include an auto-suggesting - * address bar for a browser or other navigation mechanisms that do not - * translate well to provided navigation modes.

- * - *

The display option {@link #DISPLAY_SHOW_CUSTOM} must be set for - * the custom view to be displayed.

- * - * @param resId Resource ID of a layout to inflate into the ActionBar. - * - * @see #setDisplayOptions(int, int) - */ - public abstract void setCustomView(int resId); - - /** - * Set the icon to display in the 'home' section of the action bar. - * The action bar will use an icon specified by its style or the - * activity icon by default. - * - * Whether the home section shows an icon or logo is controlled - * by the display option {@link #DISPLAY_USE_LOGO}. - * - * @param resId Resource ID of a drawable to show as an icon. - * - * @see #setDisplayUseLogoEnabled(boolean) - * @see #setDisplayShowHomeEnabled(boolean) - */ - public abstract void setIcon(int resId); - - /** - * Set the icon to display in the 'home' section of the action bar. - * The action bar will use an icon specified by its style or the - * activity icon by default. - * - * Whether the home section shows an icon or logo is controlled - * by the display option {@link #DISPLAY_USE_LOGO}. - * - * @param icon Drawable to show as an icon. - * - * @see #setDisplayUseLogoEnabled(boolean) - * @see #setDisplayShowHomeEnabled(boolean) - */ - public abstract void setIcon(Drawable icon); - - /** - * Set the logo to display in the 'home' section of the action bar. - * The action bar will use a logo specified by its style or the - * activity logo by default. - * - * Whether the home section shows an icon or logo is controlled - * by the display option {@link #DISPLAY_USE_LOGO}. - * - * @param resId Resource ID of a drawable to show as a logo. - * - * @see #setDisplayUseLogoEnabled(boolean) - * @see #setDisplayShowHomeEnabled(boolean) - */ - public abstract void setLogo(int resId); - - /** - * Set the logo to display in the 'home' section of the action bar. - * The action bar will use a logo specified by its style or the - * activity logo by default. - * - * Whether the home section shows an icon or logo is controlled - * by the display option {@link #DISPLAY_USE_LOGO}. - * - * @param logo Drawable to show as a logo. - * - * @see #setDisplayUseLogoEnabled(boolean) - * @see #setDisplayShowHomeEnabled(boolean) - */ - public abstract void setLogo(Drawable logo); - - /** - * Set the adapter and navigation callback for list navigation mode. - * - * The supplied adapter will provide views for the expanded list as well as - * the currently selected item. (These may be displayed differently.) - * - * The supplied OnNavigationListener will alert the application when the user - * changes the current list selection. - * - * @param adapter An adapter that will provide views both to display - * the current navigation selection and populate views - * within the dropdown navigation menu. - * @param callback An OnNavigationListener that will receive events when the user - * selects a navigation item. - */ - public abstract void setListNavigationCallbacks(SpinnerAdapter adapter, - OnNavigationListener callback); - - /** - * Set the selected navigation item in list or tabbed navigation modes. - * - * @param position Position of the item to select. - */ - public abstract void setSelectedNavigationItem(int position); - - /** - * Get the position of the selected navigation item in list or tabbed navigation modes. - * - * @return Position of the selected item. - */ - public abstract int getSelectedNavigationIndex(); - - /** - * Get the number of navigation items present in the current navigation mode. - * - * @return Number of navigation items. - */ - public abstract int getNavigationItemCount(); - - /** - * Set the action bar's title. This will only be displayed if - * {@link #DISPLAY_SHOW_TITLE} is set. - * - * @param title Title to set - * - * @see #setTitle(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setTitle(CharSequence title); - - /** - * Set the action bar's title. This will only be displayed if - * {@link #DISPLAY_SHOW_TITLE} is set. - * - * @param resId Resource ID of title string to set - * - * @see #setTitle(CharSequence) - * @see #setDisplayOptions(int, int) - */ - public abstract void setTitle(int resId); - - /** - * Set the action bar's subtitle. This will only be displayed if - * {@link #DISPLAY_SHOW_TITLE} is set. Set to null to disable the - * subtitle entirely. - * - * @param subtitle Subtitle to set - * - * @see #setSubtitle(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setSubtitle(CharSequence subtitle); - - /** - * Set the action bar's subtitle. This will only be displayed if - * {@link #DISPLAY_SHOW_TITLE} is set. - * - * @param resId Resource ID of subtitle string to set - * - * @see #setSubtitle(CharSequence) - * @see #setDisplayOptions(int, int) - */ - public abstract void setSubtitle(int resId); - - /** - * Set display options. This changes all display option bits at once. To change - * a limited subset of display options, see {@link #setDisplayOptions(int, int)}. - * - * @param options A combination of the bits defined by the DISPLAY_ constants - * defined in ActionBar. - */ - public abstract void setDisplayOptions(int options); - - /** - * Set selected display options. Only the options specified by mask will be changed. - * To change all display option bits at once, see {@link #setDisplayOptions(int)}. - * - *

Example: setDisplayOptions(0, DISPLAY_SHOW_HOME) will disable the - * {@link #DISPLAY_SHOW_HOME} option. - * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_SHOW_HOME | DISPLAY_USE_LOGO) - * will enable {@link #DISPLAY_SHOW_HOME} and disable {@link #DISPLAY_USE_LOGO}. - * - * @param options A combination of the bits defined by the DISPLAY_ constants - * defined in ActionBar. - * @param mask A bit mask declaring which display options should be changed. - */ - public abstract void setDisplayOptions(int options, int mask); - - /** - * Set whether to display the activity logo rather than the activity icon. - * A logo is often a wider, more detailed image. - * - *

To set several display options at once, see the setDisplayOptions methods. - * - * @param useLogo true to use the activity logo, false to use the activity icon. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setDisplayUseLogoEnabled(boolean useLogo); - - /** - * Set whether to include the application home affordance in the action bar. - * Home is presented as either an activity icon or logo. - * - *

To set several display options at once, see the setDisplayOptions methods. - * - * @param showHome true to show home, false otherwise. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setDisplayShowHomeEnabled(boolean showHome); - - /** - * Set whether home should be displayed as an "up" affordance. - * Set this to true if selecting "home" returns up by a single level in your UI - * rather than back to the top level or front page. - * - *

To set several display options at once, see the setDisplayOptions methods. - * - * @param showHomeAsUp true to show the user that selecting home will return one - * level up rather than to the top level of the app. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setDisplayHomeAsUpEnabled(boolean showHomeAsUp); - - /** - * Set whether an activity title/subtitle should be displayed. - * - *

To set several display options at once, see the setDisplayOptions methods. - * - * @param showTitle true to display a title/subtitle if present. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setDisplayShowTitleEnabled(boolean showTitle); - - /** - * Set whether a custom view should be displayed, if set. - * - *

To set several display options at once, see the setDisplayOptions methods. - * - * @param showCustom true if the currently set custom view should be displayed, false otherwise. - * - * @see #setDisplayOptions(int) - * @see #setDisplayOptions(int, int) - */ - public abstract void setDisplayShowCustomEnabled(boolean showCustom); - - /** - * Set the ActionBar's background. This will be used for the primary - * action bar. - * - * @param d Background drawable - * @see #setStackedBackgroundDrawable(Drawable) - * @see #setSplitBackgroundDrawable(Drawable) - */ - public abstract void setBackgroundDrawable(Drawable d); - - /** - * Set the ActionBar's stacked background. This will appear - * in the second row/stacked bar on some devices and configurations. - * - * @param d Background drawable for the stacked row - */ - public void setStackedBackgroundDrawable(Drawable d) { } - - /** - * Set the ActionBar's split background. This will appear in - * the split action bar containing menu-provided action buttons - * on some devices and configurations. - *

You can enable split action bar with {@link android.R.attr#uiOptions} - * - * @param d Background drawable for the split bar - */ - public void setSplitBackgroundDrawable(Drawable d) { } - - /** - * @return The current custom view. - */ - public abstract View getCustomView(); - - /** - * Returns the current ActionBar title in standard mode. - * Returns null if {@link #getNavigationMode()} would not return - * {@link #NAVIGATION_MODE_STANDARD}. - * - * @return The current ActionBar title or null. - */ - public abstract CharSequence getTitle(); - - /** - * Returns the current ActionBar subtitle in standard mode. - * Returns null if {@link #getNavigationMode()} would not return - * {@link #NAVIGATION_MODE_STANDARD}. - * - * @return The current ActionBar subtitle or null. - */ - public abstract CharSequence getSubtitle(); - - /** - * Returns the current navigation mode. The result will be one of: - *

    - *
  • {@link #NAVIGATION_MODE_STANDARD}
  • - *
  • {@link #NAVIGATION_MODE_LIST}
  • - *
  • {@link #NAVIGATION_MODE_TABS}
  • - *
- * - * @return The current navigation mode. - */ - public abstract int getNavigationMode(); - - /** - * Set the current navigation mode. - * - * @param mode The new mode to set. - * @see #NAVIGATION_MODE_STANDARD - * @see #NAVIGATION_MODE_LIST - * @see #NAVIGATION_MODE_TABS - */ - public abstract void setNavigationMode(int mode); - - /** - * @return The current set of display options. - */ - public abstract int getDisplayOptions(); - - /** - * Create and return a new {@link Tab}. - * This tab will not be included in the action bar until it is added. - * - *

Very often tabs will be used to switch between {@link Fragment} - * objects. Here is a typical implementation of such tabs:

- * - * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.java - * complete} - * - * @return A new Tab - * - * @see #addTab(Tab) - */ - public abstract Tab newTab(); - - /** - * Add a tab for use in tabbed navigation mode. The tab will be added at the end of the list. - * If this is the first tab to be added it will become the selected tab. - * - * @param tab Tab to add - */ - public abstract void addTab(Tab tab); - - /** - * Add a tab for use in tabbed navigation mode. The tab will be added at the end of the list. - * - * @param tab Tab to add - * @param setSelected True if the added tab should become the selected tab. - */ - public abstract void addTab(Tab tab, boolean setSelected); - - /** - * Add a tab for use in tabbed navigation mode. The tab will be inserted at - * position. If this is the first tab to be added it will become - * the selected tab. - * - * @param tab The tab to add - * @param position The new position of the tab - */ - public abstract void addTab(Tab tab, int position); - - /** - * Add a tab for use in tabbed navigation mode. The tab will be insterted at - * position. - * - * @param tab The tab to add - * @param position The new position of the tab - * @param setSelected True if the added tab should become the selected tab. - */ - public abstract void addTab(Tab tab, int position, boolean setSelected); - - /** - * Remove a tab from the action bar. If the removed tab was selected it will be deselected - * and another tab will be selected if present. - * - * @param tab The tab to remove - */ - public abstract void removeTab(Tab tab); - - /** - * Remove a tab from the action bar. If the removed tab was selected it will be deselected - * and another tab will be selected if present. - * - * @param position Position of the tab to remove - */ - public abstract void removeTabAt(int position); - - /** - * Remove all tabs from the action bar and deselect the current tab. - */ - public abstract void removeAllTabs(); - - /** - * Select the specified tab. If it is not a child of this action bar it will be added. - * - *

Note: If you want to select by index, use {@link #setSelectedNavigationItem(int)}.

- * - * @param tab Tab to select - */ - public abstract void selectTab(Tab tab); - - /** - * Returns the currently selected tab if in tabbed navigation mode and there is at least - * one tab present. - * - * @return The currently selected tab or null - */ - public abstract Tab getSelectedTab(); - - /** - * Returns the tab at the specified index. - * - * @param index Index value in the range 0-get - * @return - */ - public abstract Tab getTabAt(int index); - - /** - * Returns the number of tabs currently registered with the action bar. - * @return Tab count - */ - public abstract int getTabCount(); - - /** - * Retrieve the current height of the ActionBar. - * - * @return The ActionBar's height - */ - public abstract int getHeight(); - - /** - * Show the ActionBar if it is not currently showing. - * If the window hosting the ActionBar does not have the feature - * {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application - * content to fit the new space available. - */ - public abstract void show(); - - /** - * Hide the ActionBar if it is currently showing. - * If the window hosting the ActionBar does not have the feature - * {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application - * content to fit the new space available. - */ - public abstract void hide(); - - /** - * @return true if the ActionBar is showing, false otherwise. - */ - public abstract boolean isShowing(); - - /** - * Add a listener that will respond to menu visibility change events. - * - * @param listener The new listener to add - */ - public abstract void addOnMenuVisibilityListener(OnMenuVisibilityListener listener); - - /** - * Remove a menu visibility listener. This listener will no longer receive menu - * visibility change events. - * - * @param listener A listener to remove that was previously added - */ - public abstract void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener); - - /** - * Enable or disable the "home" button in the corner of the action bar. (Note that this - * is the application home/up affordance on the action bar, not the systemwide home - * button.) - * - *

This defaults to true for packages targeting < API 14. For packages targeting - * API 14 or greater, the application should call this method to enable interaction - * with the home/up affordance. - * - *

Setting the {@link #DISPLAY_HOME_AS_UP} display option will automatically enable - * the home button. - * - * @param enabled true to enable the home button, false to disable the home button. - */ - public void setHomeButtonEnabled(boolean enabled) { } - - /** - * Returns a {@link Context} with an appropriate theme for creating views that - * will appear in the action bar. If you are inflating or instantiating custom views - * that will appear in an action bar, you should use the Context returned by this method. - * (This includes adapters used for list navigation mode.) - * This will ensure that views contrast properly against the action bar. - * - * @return A themed Context for creating views - */ - public Context getThemedContext() { return null; } - - /** - * Listener interface for ActionBar navigation events. - */ - public interface OnNavigationListener { - /** - * This method is called whenever a navigation item in your action bar - * is selected. - * - * @param itemPosition Position of the item clicked. - * @param itemId ID of the item clicked. - * @return True if the event was handled, false otherwise. - */ - public boolean onNavigationItemSelected(int itemPosition, long itemId); - } - - /** - * Listener for receiving events when action bar menus are shown or hidden. - */ - public interface OnMenuVisibilityListener { - /** - * Called when an action bar menu is shown or hidden. Applications may want to use - * this to tune auto-hiding behavior for the action bar or pause/resume video playback, - * gameplay, or other activity within the main content area. - * - * @param isVisible True if an action bar menu is now visible, false if no action bar - * menus are visible. - */ - public void onMenuVisibilityChanged(boolean isVisible); - } - - /** - * A tab in the action bar. - * - *

Tabs manage the hiding and showing of {@link Fragment}s. - */ - public static abstract class Tab { - /** - * An invalid position for a tab. - * - * @see #getPosition() - */ - public static final int INVALID_POSITION = -1; - - /** - * Return the current position of this tab in the action bar. - * - * @return Current position, or {@link #INVALID_POSITION} if this tab is not currently in - * the action bar. - */ - public abstract int getPosition(); - - /** - * Return the icon associated with this tab. - * - * @return The tab's icon - */ - public abstract Drawable getIcon(); - - /** - * Return the text of this tab. - * - * @return The tab's text - */ - public abstract CharSequence getText(); - - /** - * Set the icon displayed on this tab. - * - * @param icon The drawable to use as an icon - * @return The current instance for call chaining - */ - public abstract Tab setIcon(Drawable icon); - - /** - * Set the icon displayed on this tab. - * - * @param resId Resource ID referring to the drawable to use as an icon - * @return The current instance for call chaining - */ - public abstract Tab setIcon(int resId); - - /** - * Set the text displayed on this tab. Text may be truncated if there is not - * room to display the entire string. - * - * @param text The text to display - * @return The current instance for call chaining - */ - public abstract Tab setText(CharSequence text); - - /** - * Set the text displayed on this tab. Text may be truncated if there is not - * room to display the entire string. - * - * @param resId A resource ID referring to the text that should be displayed - * @return The current instance for call chaining - */ - public abstract Tab setText(int resId); - - /** - * Set a custom view to be used for this tab. This overrides values set by - * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}. - * - * @param view Custom view to be used as a tab. - * @return The current instance for call chaining - */ - public abstract Tab setCustomView(View view); - - /** - * Set a custom view to be used for this tab. This overrides values set by - * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}. - * - * @param layoutResId A layout resource to inflate and use as a custom tab view - * @return The current instance for call chaining - */ - public abstract Tab setCustomView(int layoutResId); - - /** - * Retrieve a previously set custom view for this tab. - * - * @return The custom view set by {@link #setCustomView(View)}. - */ - public abstract View getCustomView(); - - /** - * Give this Tab an arbitrary object to hold for later use. - * - * @param obj Object to store - * @return The current instance for call chaining - */ - public abstract Tab setTag(Object obj); - - /** - * @return This Tab's tag object. - */ - public abstract Object getTag(); - - /** - * Set the {@link TabListener} that will handle switching to and from this tab. - * All tabs must have a TabListener set before being added to the ActionBar. - * - * @param listener Listener to handle tab selection events - * @return The current instance for call chaining - */ - public abstract Tab setTabListener(TabListener listener); - - /** - * Select this tab. Only valid if the tab has been added to the action bar. - */ - public abstract void select(); - - /** - * Set a description of this tab's content for use in accessibility support. - * If no content description is provided the title will be used. - * - * @param resId A resource ID referring to the description text - * @return The current instance for call chaining - * @see #setContentDescription(CharSequence) - * @see #getContentDescription() - */ - public abstract Tab setContentDescription(int resId); - - /** - * Set a description of this tab's content for use in accessibility support. - * If no content description is provided the title will be used. - * - * @param contentDesc Description of this tab's content - * @return The current instance for call chaining - * @see #setContentDescription(int) - * @see #getContentDescription() - */ - public abstract Tab setContentDescription(CharSequence contentDesc); - - /** - * Gets a brief description of this tab's content for use in accessibility support. - * - * @return Description of this tab's content - * @see #setContentDescription(CharSequence) - * @see #setContentDescription(int) - */ - public abstract CharSequence getContentDescription(); - } - - /** - * Callback interface invoked when a tab is focused, unfocused, added, or removed. - */ - public interface TabListener { - /** - * Called when a tab enters the selected state. - * - * @param tab The tab that was selected - * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute - * during a tab switch. The previous tab's unselect and this tab's select will be - * executed in a single transaction. This FragmentTransaction does not support - * being added to the back stack. - */ - public void onTabSelected(Tab tab, FragmentTransaction ft); - - /** - * Called when a tab exits the selected state. - * - * @param tab The tab that was unselected - * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute - * during a tab switch. This tab's unselect and the newly selected tab's select - * will be executed in a single transaction. This FragmentTransaction does not - * support being added to the back stack. - */ - public void onTabUnselected(Tab tab, FragmentTransaction ft); - - /** - * Called when a tab that is already selected is chosen again by the user. - * Some applications may use this action to return to the top level of a category. - * - * @param tab The tab that was reselected. - * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute - * once this method returns. This FragmentTransaction does not support - * being added to the back stack. - */ - public void onTabReselected(Tab tab, FragmentTransaction ft); - } - - /** - * Per-child layout information associated with action bar custom views. - * - * @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity - */ - public static class LayoutParams extends MarginLayoutParams { - private static final int[] ATTRS = new int[] { - android.R.attr.layout_gravity - }; - - /** - * Gravity for the view associated with these LayoutParams. - * - * @see android.view.Gravity - */ - @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = -1, to = "NONE"), - @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"), - @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"), - @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"), - @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"), - @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"), - @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"), - @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"), - @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"), - @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"), - @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"), - @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL") - }) - public int gravity = -1; - - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - - TypedArray a = c.obtainStyledAttributes(attrs, ATTRS); - gravity = a.getInt(0, -1); - a.recycle(); - } - - public LayoutParams(int width, int height) { - super(width, height); - this.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT; - } - - public LayoutParams(int width, int height, int gravity) { - super(width, height); - this.gravity = gravity; - } - - public LayoutParams(int gravity) { - this(WRAP_CONTENT, FILL_PARENT, gravity); - } - - public LayoutParams(LayoutParams source) { - super(source); - - this.gravity = source.gravity; - } - - public LayoutParams(ViewGroup.LayoutParams source) { - super(source); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java deleted file mode 100644 index 7b4543640..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.actionbarsherlock.app; - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.Window; -import android.view.ViewGroup.LayoutParams; -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; -import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; -import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; -import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -public abstract class SherlockActivity extends Activity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { - private ActionBarSherlock mSherlock; - - protected final ActionBarSherlock getSherlock() { - if (mSherlock == null) { - mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); - } - return mSherlock; - } - - - /////////////////////////////////////////////////////////////////////////// - // Action bar and mode - /////////////////////////////////////////////////////////////////////////// - - public ActionBar getSupportActionBar() { - return getSherlock().getActionBar(); - } - - public ActionMode startActionMode(ActionMode.Callback callback) { - return getSherlock().startActionMode(callback); - } - - @Override - public void onActionModeStarted(ActionMode mode) {} - - @Override - public void onActionModeFinished(ActionMode mode) {} - - - /////////////////////////////////////////////////////////////////////////// - // General lifecycle/callback dispatching - /////////////////////////////////////////////////////////////////////////// - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getSherlock().dispatchConfigurationChanged(newConfig); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getSherlock().dispatchPostResume(); - } - - @Override - protected void onPause() { - getSherlock().dispatchPause(); - super.onPause(); - } - - @Override - protected void onStop() { - getSherlock().dispatchStop(); - super.onStop(); - } - - @Override - protected void onDestroy() { - getSherlock().dispatchDestroy(); - super.onDestroy(); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - getSherlock().dispatchPostCreate(savedInstanceState); - super.onPostCreate(savedInstanceState); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - getSherlock().dispatchTitleChanged(title, color); - super.onTitleChanged(title, color); - } - - @Override - public final boolean onMenuOpened(int featureId, android.view.Menu menu) { - if (getSherlock().dispatchMenuOpened(featureId, menu)) { - return true; - } - return super.onMenuOpened(featureId, menu); - } - - @Override - public void onPanelClosed(int featureId, android.view.Menu menu) { - getSherlock().dispatchPanelClosed(featureId, menu); - super.onPanelClosed(featureId, menu); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (getSherlock().dispatchKeyEvent(event)) { - return true; - } - return super.dispatchKeyEvent(event); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - getSherlock().dispatchSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - getSherlock().dispatchRestoreInstanceState(savedInstanceState); - } - - /////////////////////////////////////////////////////////////////////////// - // Native menu handling - /////////////////////////////////////////////////////////////////////////// - - public MenuInflater getSupportMenuInflater() { - return getSherlock().getMenuInflater(); - } - - public void invalidateOptionsMenu() { - getSherlock().dispatchInvalidateOptionsMenu(); - } - - public void supportInvalidateOptionsMenu() { - invalidateOptionsMenu(); - } - - @Override - public final boolean onCreateOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchCreateOptionsMenu(menu); - } - - @Override - public final boolean onPrepareOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchPrepareOptionsMenu(menu); - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return getSherlock().dispatchOptionsItemSelected(item); - } - - @Override - public void openOptionsMenu() { - if (!getSherlock().dispatchOpenOptionsMenu()) { - super.openOptionsMenu(); - } - } - - @Override - public void closeOptionsMenu() { - if (!getSherlock().dispatchCloseOptionsMenu()) { - super.closeOptionsMenu(); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Sherlock menu handling - /////////////////////////////////////////////////////////////////////////// - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onCreateOptionsMenu(menu); - } - return false; - } - - public boolean onCreateOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onPrepareOptionsMenu(menu); - } - return false; - } - - public boolean onPrepareOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onOptionsItemSelected(item); - } - return false; - } - - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - - /////////////////////////////////////////////////////////////////////////// - // Content - /////////////////////////////////////////////////////////////////////////// - - @Override - public void addContentView(View view, LayoutParams params) { - getSherlock().addContentView(view, params); - } - - @Override - public void setContentView(int layoutResId) { - getSherlock().setContentView(layoutResId); - } - - @Override - public void setContentView(View view, LayoutParams params) { - getSherlock().setContentView(view, params); - } - - @Override - public void setContentView(View view) { - getSherlock().setContentView(view); - } - - public void requestWindowFeature(long featureId) { - getSherlock().requestFeature((int)featureId); - } - - - /////////////////////////////////////////////////////////////////////////// - // Progress Indication - /////////////////////////////////////////////////////////////////////////// - - public void setSupportProgress(int progress) { - getSherlock().setProgress(progress); - } - - public void setSupportProgressBarIndeterminate(boolean indeterminate) { - getSherlock().setProgressBarIndeterminate(indeterminate); - } - - public void setSupportProgressBarIndeterminateVisibility(boolean visible) { - getSherlock().setProgressBarIndeterminateVisibility(visible); - } - - public void setSupportProgressBarVisibility(boolean visible) { - getSherlock().setProgressBarVisibility(visible); - } - - public void setSupportSecondaryProgress(int secondaryProgress) { - getSherlock().setSecondaryProgress(secondaryProgress); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java deleted file mode 100644 index a7c856bf0..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.actionbarsherlock.app; - -import android.app.Activity; -import android.support.v4.app.DialogFragment; -import com.actionbarsherlock.internal.view.menu.MenuItemWrapper; -import com.actionbarsherlock.internal.view.menu.MenuWrapper; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnCreateOptionsMenuListener; -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnOptionsItemSelectedListener; -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnPrepareOptionsMenuListener; - -public class SherlockDialogFragment extends DialogFragment implements OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener, OnOptionsItemSelectedListener { - private SherlockFragmentActivity mActivity; - - public SherlockFragmentActivity getSherlockActivity() { - return mActivity; - } - - @Override - public void onAttach(Activity activity) { - if (!(activity instanceof SherlockFragmentActivity)) { - throw new IllegalStateException(getClass().getSimpleName() + " must be attached to a SherlockFragmentActivity."); - } - mActivity = (SherlockFragmentActivity)activity; - - super.onAttach(activity); - } - - @Override - public void onDetach() { - mActivity = null; - super.onDetach(); - } - - @Override - public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { - onCreateOptionsMenu(new MenuWrapper(menu), mActivity.getSupportMenuInflater()); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - //Nothing to see here. - } - - @Override - public final void onPrepareOptionsMenu(android.view.Menu menu) { - onPrepareOptionsMenu(new MenuWrapper(menu)); - } - - @Override - public void onPrepareOptionsMenu(Menu menu) { - //Nothing to see here. - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return onOptionsItemSelected(new MenuItemWrapper(item)); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - //Nothing to see here. - return false; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java deleted file mode 100644 index 078f9b0ca..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.actionbarsherlock.app; - -import android.app.ExpandableListActivity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.Window; -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; -import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; -import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; -import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -public abstract class SherlockExpandableListActivity extends ExpandableListActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { - private ActionBarSherlock mSherlock; - - protected final ActionBarSherlock getSherlock() { - if (mSherlock == null) { - mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); - } - return mSherlock; - } - - - /////////////////////////////////////////////////////////////////////////// - // Action bar and mode - /////////////////////////////////////////////////////////////////////////// - - public ActionBar getSupportActionBar() { - return getSherlock().getActionBar(); - } - - public ActionMode startActionMode(ActionMode.Callback callback) { - return getSherlock().startActionMode(callback); - } - - @Override - public void onActionModeStarted(ActionMode mode) {} - - @Override - public void onActionModeFinished(ActionMode mode) {} - - - /////////////////////////////////////////////////////////////////////////// - // General lifecycle/callback dispatching - /////////////////////////////////////////////////////////////////////////// - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getSherlock().dispatchConfigurationChanged(newConfig); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getSherlock().dispatchPostResume(); - } - - @Override - protected void onPause() { - getSherlock().dispatchPause(); - super.onPause(); - } - - @Override - protected void onStop() { - getSherlock().dispatchStop(); - super.onStop(); - } - - @Override - protected void onDestroy() { - getSherlock().dispatchDestroy(); - super.onDestroy(); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - getSherlock().dispatchPostCreate(savedInstanceState); - super.onPostCreate(savedInstanceState); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - getSherlock().dispatchTitleChanged(title, color); - super.onTitleChanged(title, color); - } - - @Override - public final boolean onMenuOpened(int featureId, android.view.Menu menu) { - if (getSherlock().dispatchMenuOpened(featureId, menu)) { - return true; - } - return super.onMenuOpened(featureId, menu); - } - - @Override - public void onPanelClosed(int featureId, android.view.Menu menu) { - getSherlock().dispatchPanelClosed(featureId, menu); - super.onPanelClosed(featureId, menu); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (getSherlock().dispatchKeyEvent(event)) { - return true; - } - return super.dispatchKeyEvent(event); - } - - - /////////////////////////////////////////////////////////////////////////// - // Native menu handling - /////////////////////////////////////////////////////////////////////////// - - public MenuInflater getSupportMenuInflater() { - return getSherlock().getMenuInflater(); - } - - public void invalidateOptionsMenu() { - getSherlock().dispatchInvalidateOptionsMenu(); - } - - public void supportInvalidateOptionsMenu() { - invalidateOptionsMenu(); - } - - @Override - public final boolean onCreateOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchCreateOptionsMenu(menu); - } - - @Override - public final boolean onPrepareOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchPrepareOptionsMenu(menu); - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return getSherlock().dispatchOptionsItemSelected(item); - } - - @Override - public void openOptionsMenu() { - if (!getSherlock().dispatchOpenOptionsMenu()) { - super.openOptionsMenu(); - } - } - - @Override - public void closeOptionsMenu() { - if (!getSherlock().dispatchCloseOptionsMenu()) { - super.closeOptionsMenu(); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Sherlock menu handling - /////////////////////////////////////////////////////////////////////////// - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onCreateOptionsMenu(menu); - } - return false; - } - - public boolean onCreateOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onPrepareOptionsMenu(menu); - } - return false; - } - - public boolean onPrepareOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onOptionsItemSelected(item); - } - return false; - } - - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - - /////////////////////////////////////////////////////////////////////////// - // Content - /////////////////////////////////////////////////////////////////////////// - - @Override - public void addContentView(View view, LayoutParams params) { - getSherlock().addContentView(view, params); - } - - @Override - public void setContentView(int layoutResId) { - getSherlock().setContentView(layoutResId); - } - - @Override - public void setContentView(View view, LayoutParams params) { - getSherlock().setContentView(view, params); - } - - @Override - public void setContentView(View view) { - getSherlock().setContentView(view); - } - - public void requestWindowFeature(long featureId) { - getSherlock().requestFeature((int)featureId); - } - - - /////////////////////////////////////////////////////////////////////////// - // Progress Indication - /////////////////////////////////////////////////////////////////////////// - - public void setSupportProgress(int progress) { - getSherlock().setProgress(progress); - } - - public void setSupportProgressBarIndeterminate(boolean indeterminate) { - getSherlock().setProgressBarIndeterminate(indeterminate); - } - - public void setSupportProgressBarIndeterminateVisibility(boolean visible) { - getSherlock().setProgressBarIndeterminateVisibility(visible); - } - - public void setSupportProgressBarVisibility(boolean visible) { - getSherlock().setProgressBarVisibility(visible); - } - - public void setSupportSecondaryProgress(int secondaryProgress) { - getSherlock().setSecondaryProgress(secondaryProgress); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java deleted file mode 100644 index 0f24e9c85..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.actionbarsherlock.app; - -import android.app.Activity; -import android.support.v4.app.Fragment; -import com.actionbarsherlock.internal.view.menu.MenuItemWrapper; -import com.actionbarsherlock.internal.view.menu.MenuWrapper; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnCreateOptionsMenuListener; -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnOptionsItemSelectedListener; -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnPrepareOptionsMenuListener; - -public class SherlockFragment extends Fragment implements OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener, OnOptionsItemSelectedListener { - private SherlockFragmentActivity mActivity; - - public SherlockFragmentActivity getSherlockActivity() { - return mActivity; - } - - @Override - public void onAttach(Activity activity) { - if (!(activity instanceof SherlockFragmentActivity)) { - throw new IllegalStateException(getClass().getSimpleName() + " must be attached to a SherlockFragmentActivity."); - } - mActivity = (SherlockFragmentActivity)activity; - - super.onAttach(activity); - } - - @Override - public void onDetach() { - mActivity = null; - super.onDetach(); - } - - @Override - public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { - onCreateOptionsMenu(new MenuWrapper(menu), mActivity.getSupportMenuInflater()); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - //Nothing to see here. - } - - @Override - public final void onPrepareOptionsMenu(android.view.Menu menu) { - onPrepareOptionsMenu(new MenuWrapper(menu)); - } - - @Override - public void onPrepareOptionsMenu(Menu menu) { - //Nothing to see here. - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return onOptionsItemSelected(new MenuItemWrapper(item)); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - //Nothing to see here. - return false; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java deleted file mode 100644 index 3d092f033..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java +++ /dev/null @@ -1,303 +0,0 @@ -package com.actionbarsherlock.app; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.support.v4.app.Watson; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.Window; -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -import static com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; -import static com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; - -/** @see {@link android.support.v4.app.Watson} */ -public class SherlockFragmentActivity extends Watson implements OnActionModeStartedListener, OnActionModeFinishedListener { - private static final boolean DEBUG = false; - private static final String TAG = "SherlockFragmentActivity"; - - private ActionBarSherlock mSherlock; - private boolean mIgnoreNativeCreate = false; - private boolean mIgnoreNativePrepare = false; - private boolean mIgnoreNativeSelected = false; - - protected final ActionBarSherlock getSherlock() { - if (mSherlock == null) { - mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); - } - return mSherlock; - } - - - /////////////////////////////////////////////////////////////////////////// - // Action bar and mode - /////////////////////////////////////////////////////////////////////////// - - public ActionBar getSupportActionBar() { - return getSherlock().getActionBar(); - } - - public ActionMode startActionMode(ActionMode.Callback callback) { - return getSherlock().startActionMode(callback); - } - - @Override - public void onActionModeStarted(ActionMode mode) {} - - @Override - public void onActionModeFinished(ActionMode mode) {} - - - /////////////////////////////////////////////////////////////////////////// - // General lifecycle/callback dispatching - /////////////////////////////////////////////////////////////////////////// - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getSherlock().dispatchConfigurationChanged(newConfig); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getSherlock().dispatchPostResume(); - } - - @Override - protected void onPause() { - getSherlock().dispatchPause(); - super.onPause(); - } - - @Override - protected void onStop() { - getSherlock().dispatchStop(); - super.onStop(); - } - - @Override - protected void onDestroy() { - getSherlock().dispatchDestroy(); - super.onDestroy(); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - getSherlock().dispatchPostCreate(savedInstanceState); - super.onPostCreate(savedInstanceState); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - getSherlock().dispatchTitleChanged(title, color); - super.onTitleChanged(title, color); - } - - @Override - public final boolean onMenuOpened(int featureId, android.view.Menu menu) { - if (getSherlock().dispatchMenuOpened(featureId, menu)) { - return true; - } - return super.onMenuOpened(featureId, menu); - } - - @Override - public void onPanelClosed(int featureId, android.view.Menu menu) { - getSherlock().dispatchPanelClosed(featureId, menu); - super.onPanelClosed(featureId, menu); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (getSherlock().dispatchKeyEvent(event)) { - return true; - } - return super.dispatchKeyEvent(event); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - getSherlock().dispatchSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - getSherlock().dispatchRestoreInstanceState(savedInstanceState); - } - - /////////////////////////////////////////////////////////////////////////// - // Native menu handling - /////////////////////////////////////////////////////////////////////////// - - public MenuInflater getSupportMenuInflater() { - if (DEBUG) Log.d(TAG, "[getSupportMenuInflater]"); - - return getSherlock().getMenuInflater(); - } - - public void invalidateOptionsMenu() { - if (DEBUG) Log.d(TAG, "[invalidateOptionsMenu]"); - - getSherlock().dispatchInvalidateOptionsMenu(); - } - - public void supportInvalidateOptionsMenu() { - if (DEBUG) Log.d(TAG, "[supportInvalidateOptionsMenu]"); - - invalidateOptionsMenu(); - } - - @Override - public final boolean onCreatePanelMenu(int featureId, android.view.Menu menu) { - if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] featureId: " + featureId + ", menu: " + menu); - - if (featureId == Window.FEATURE_OPTIONS_PANEL && !mIgnoreNativeCreate) { - mIgnoreNativeCreate = true; - boolean result = getSherlock().dispatchCreateOptionsMenu(menu); - mIgnoreNativeCreate = false; - - if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] returning " + result); - return result; - } - return super.onCreatePanelMenu(featureId, menu); - } - - @Override - public final boolean onCreateOptionsMenu(android.view.Menu menu) { - return true; - } - - @Override - public final boolean onPreparePanel(int featureId, View view, android.view.Menu menu) { - if (DEBUG) Log.d(TAG, "[onPreparePanel] featureId: " + featureId + ", view: " + view + ", menu: " + menu); - - if (featureId == Window.FEATURE_OPTIONS_PANEL && !mIgnoreNativePrepare) { - mIgnoreNativePrepare = true; - boolean result = getSherlock().dispatchPrepareOptionsMenu(menu); - mIgnoreNativePrepare = false; - - if (DEBUG) Log.d(TAG, "[onPreparePanel] returning " + result); - return result; - } - return super.onPreparePanel(featureId, view, menu); - } - - @Override - public final boolean onPrepareOptionsMenu(android.view.Menu menu) { - return true; - } - - @Override - public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) { - if (DEBUG) Log.d(TAG, "[onMenuItemSelected] featureId: " + featureId + ", item: " + item); - - if (featureId == Window.FEATURE_OPTIONS_PANEL && !mIgnoreNativeSelected) { - mIgnoreNativeSelected = true; - boolean result = getSherlock().dispatchOptionsItemSelected(item); - mIgnoreNativeSelected = false; - - if (DEBUG) Log.d(TAG, "[onMenuItemSelected] returning " + result); - return result; - } - return super.onMenuItemSelected(featureId, item); - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return false; - } - - @Override - public void openOptionsMenu() { - if (!getSherlock().dispatchOpenOptionsMenu()) { - super.openOptionsMenu(); - } - } - - @Override - public void closeOptionsMenu() { - if (!getSherlock().dispatchCloseOptionsMenu()) { - super.closeOptionsMenu(); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Sherlock menu handling - /////////////////////////////////////////////////////////////////////////// - - public boolean onCreateOptionsMenu(Menu menu) { - return true; - } - - public boolean onPrepareOptionsMenu(Menu menu) { - return true; - } - - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - - /////////////////////////////////////////////////////////////////////////// - // Content - /////////////////////////////////////////////////////////////////////////// - - @Override - public void addContentView(View view, LayoutParams params) { - getSherlock().addContentView(view, params); - } - - @Override - public void setContentView(int layoutResId) { - getSherlock().setContentView(layoutResId); - } - - @Override - public void setContentView(View view, LayoutParams params) { - getSherlock().setContentView(view, params); - } - - @Override - public void setContentView(View view) { - getSherlock().setContentView(view); - } - - public void requestWindowFeature(long featureId) { - getSherlock().requestFeature((int)featureId); - } - - - /////////////////////////////////////////////////////////////////////////// - // Progress Indication - /////////////////////////////////////////////////////////////////////////// - - public void setSupportProgress(int progress) { - getSherlock().setProgress(progress); - } - - public void setSupportProgressBarIndeterminate(boolean indeterminate) { - getSherlock().setProgressBarIndeterminate(indeterminate); - } - - public void setSupportProgressBarIndeterminateVisibility(boolean visible) { - getSherlock().setProgressBarIndeterminateVisibility(visible); - } - - public void setSupportProgressBarVisibility(boolean visible) { - getSherlock().setProgressBarVisibility(visible); - } - - public void setSupportSecondaryProgress(int secondaryProgress) { - getSherlock().setSecondaryProgress(secondaryProgress); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java deleted file mode 100644 index aba6d85e8..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.actionbarsherlock.app; - -import android.app.ListActivity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.view.Window; -import android.view.ViewGroup.LayoutParams; -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; -import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; -import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; -import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -public abstract class SherlockListActivity extends ListActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { - private ActionBarSherlock mSherlock; - - protected final ActionBarSherlock getSherlock() { - if (mSherlock == null) { - mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); - } - return mSherlock; - } - - - /////////////////////////////////////////////////////////////////////////// - // Action bar and mode - /////////////////////////////////////////////////////////////////////////// - - public ActionBar getSupportActionBar() { - return getSherlock().getActionBar(); - } - - public ActionMode startActionMode(ActionMode.Callback callback) { - return getSherlock().startActionMode(callback); - } - - @Override - public void onActionModeStarted(ActionMode mode) {} - - @Override - public void onActionModeFinished(ActionMode mode) {} - - - /////////////////////////////////////////////////////////////////////////// - // General lifecycle/callback dispatching - /////////////////////////////////////////////////////////////////////////// - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getSherlock().dispatchConfigurationChanged(newConfig); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getSherlock().dispatchPostResume(); - } - - @Override - protected void onPause() { - getSherlock().dispatchPause(); - super.onPause(); - } - - @Override - protected void onStop() { - getSherlock().dispatchStop(); - super.onStop(); - } - - @Override - protected void onDestroy() { - getSherlock().dispatchDestroy(); - super.onDestroy(); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - getSherlock().dispatchPostCreate(savedInstanceState); - super.onPostCreate(savedInstanceState); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - getSherlock().dispatchTitleChanged(title, color); - super.onTitleChanged(title, color); - } - - @Override - public final boolean onMenuOpened(int featureId, android.view.Menu menu) { - if (getSherlock().dispatchMenuOpened(featureId, menu)) { - return true; - } - return super.onMenuOpened(featureId, menu); - } - - @Override - public void onPanelClosed(int featureId, android.view.Menu menu) { - getSherlock().dispatchPanelClosed(featureId, menu); - super.onPanelClosed(featureId, menu); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (getSherlock().dispatchKeyEvent(event)) { - return true; - } - return super.dispatchKeyEvent(event); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - getSherlock().dispatchSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - getSherlock().dispatchRestoreInstanceState(savedInstanceState); - } - - /////////////////////////////////////////////////////////////////////////// - // Native menu handling - /////////////////////////////////////////////////////////////////////////// - - public MenuInflater getSupportMenuInflater() { - return getSherlock().getMenuInflater(); - } - - public void invalidateOptionsMenu() { - getSherlock().dispatchInvalidateOptionsMenu(); - } - - public void supportInvalidateOptionsMenu() { - invalidateOptionsMenu(); - } - - @Override - public final boolean onCreateOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchCreateOptionsMenu(menu); - } - - @Override - public final boolean onPrepareOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchPrepareOptionsMenu(menu); - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return getSherlock().dispatchOptionsItemSelected(item); - } - - @Override - public void openOptionsMenu() { - if (!getSherlock().dispatchOpenOptionsMenu()) { - super.openOptionsMenu(); - } - } - - @Override - public void closeOptionsMenu() { - if (!getSherlock().dispatchCloseOptionsMenu()) { - super.closeOptionsMenu(); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Sherlock menu handling - /////////////////////////////////////////////////////////////////////////// - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onCreateOptionsMenu(menu); - } - return false; - } - - public boolean onCreateOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onPrepareOptionsMenu(menu); - } - return false; - } - - public boolean onPrepareOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onOptionsItemSelected(item); - } - return false; - } - - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - - /////////////////////////////////////////////////////////////////////////// - // Content - /////////////////////////////////////////////////////////////////////////// - - @Override - public void addContentView(View view, LayoutParams params) { - getSherlock().addContentView(view, params); - } - - @Override - public void setContentView(int layoutResId) { - getSherlock().setContentView(layoutResId); - } - - @Override - public void setContentView(View view, LayoutParams params) { - getSherlock().setContentView(view, params); - } - - @Override - public void setContentView(View view) { - getSherlock().setContentView(view); - } - - public void requestWindowFeature(long featureId) { - getSherlock().requestFeature((int)featureId); - } - - - /////////////////////////////////////////////////////////////////////////// - // Progress Indication - /////////////////////////////////////////////////////////////////////////// - - public void setSupportProgress(int progress) { - getSherlock().setProgress(progress); - } - - public void setSupportProgressBarIndeterminate(boolean indeterminate) { - getSherlock().setProgressBarIndeterminate(indeterminate); - } - - public void setSupportProgressBarIndeterminateVisibility(boolean visible) { - getSherlock().setProgressBarIndeterminateVisibility(visible); - } - - public void setSupportProgressBarVisibility(boolean visible) { - getSherlock().setProgressBarVisibility(visible); - } - - public void setSupportSecondaryProgress(int secondaryProgress) { - getSherlock().setSecondaryProgress(secondaryProgress); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java deleted file mode 100644 index 13ca3c49f..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.actionbarsherlock.app; - -import android.app.Activity; -import android.support.v4.app.ListFragment; -import com.actionbarsherlock.internal.view.menu.MenuItemWrapper; -import com.actionbarsherlock.internal.view.menu.MenuWrapper; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnCreateOptionsMenuListener; -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnOptionsItemSelectedListener; -import static com.actionbarsherlock.app.SherlockFragmentActivity.OnPrepareOptionsMenuListener; - -public class SherlockListFragment extends ListFragment implements OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener, OnOptionsItemSelectedListener { - private SherlockFragmentActivity mActivity; - - public SherlockFragmentActivity getSherlockActivity() { - return mActivity; - } - - @Override - public void onAttach(Activity activity) { - if (!(activity instanceof SherlockFragmentActivity)) { - throw new IllegalStateException(getClass().getSimpleName() + " must be attached to a SherlockFragmentActivity."); - } - mActivity = (SherlockFragmentActivity)activity; - - super.onAttach(activity); - } - - @Override - public void onDetach() { - mActivity = null; - super.onDetach(); - } - - @Override - public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { - onCreateOptionsMenu(new MenuWrapper(menu), mActivity.getSupportMenuInflater()); - } - - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - //Nothing to see here. - } - - @Override - public final void onPrepareOptionsMenu(android.view.Menu menu) { - onPrepareOptionsMenu(new MenuWrapper(menu)); - } - - @Override - public void onPrepareOptionsMenu(Menu menu) { - //Nothing to see here. - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return onOptionsItemSelected(new MenuItemWrapper(item)); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - //Nothing to see here. - return false; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java deleted file mode 100644 index bee72cb25..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.actionbarsherlock.app; - -import android.content.res.Configuration; -import android.os.Bundle; -import android.preference.PreferenceActivity; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.Window; -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; -import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; -import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; -import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; -import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -public abstract class SherlockPreferenceActivity extends PreferenceActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { - private ActionBarSherlock mSherlock; - - protected final ActionBarSherlock getSherlock() { - if (mSherlock == null) { - mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); - } - return mSherlock; - } - - - /////////////////////////////////////////////////////////////////////////// - // Action bar and mode - /////////////////////////////////////////////////////////////////////////// - - public ActionBar getSupportActionBar() { - return getSherlock().getActionBar(); - } - - public ActionMode startActionMode(ActionMode.Callback callback) { - return getSherlock().startActionMode(callback); - } - - @Override - public void onActionModeStarted(ActionMode mode) {} - - @Override - public void onActionModeFinished(ActionMode mode) {} - - - /////////////////////////////////////////////////////////////////////////// - // General lifecycle/callback dispatching - /////////////////////////////////////////////////////////////////////////// - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - getSherlock().dispatchConfigurationChanged(newConfig); - } - - @Override - protected void onPostResume() { - super.onPostResume(); - getSherlock().dispatchPostResume(); - } - - @Override - protected void onPause() { - getSherlock().dispatchPause(); - super.onPause(); - } - - @Override - protected void onStop() { - getSherlock().dispatchStop(); - super.onStop(); - } - - @Override - protected void onDestroy() { - getSherlock().dispatchDestroy(); - super.onDestroy(); - } - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - getSherlock().dispatchPostCreate(savedInstanceState); - super.onPostCreate(savedInstanceState); - } - - @Override - protected void onTitleChanged(CharSequence title, int color) { - getSherlock().dispatchTitleChanged(title, color); - super.onTitleChanged(title, color); - } - - @Override - public final boolean onMenuOpened(int featureId, android.view.Menu menu) { - if (getSherlock().dispatchMenuOpened(featureId, menu)) { - return true; - } - return super.onMenuOpened(featureId, menu); - } - - @Override - public void onPanelClosed(int featureId, android.view.Menu menu) { - getSherlock().dispatchPanelClosed(featureId, menu); - super.onPanelClosed(featureId, menu); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (getSherlock().dispatchKeyEvent(event)) { - return true; - } - return super.dispatchKeyEvent(event); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - getSherlock().dispatchSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - getSherlock().dispatchRestoreInstanceState(savedInstanceState); - } - - /////////////////////////////////////////////////////////////////////////// - // Native menu handling - /////////////////////////////////////////////////////////////////////////// - - public MenuInflater getSupportMenuInflater() { - return getSherlock().getMenuInflater(); - } - - public void invalidateOptionsMenu() { - getSherlock().dispatchInvalidateOptionsMenu(); - } - - public void supportInvalidateOptionsMenu() { - invalidateOptionsMenu(); - } - - @Override - public final boolean onCreateOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchCreateOptionsMenu(menu); - } - - @Override - public final boolean onPrepareOptionsMenu(android.view.Menu menu) { - return getSherlock().dispatchPrepareOptionsMenu(menu); - } - - @Override - public final boolean onOptionsItemSelected(android.view.MenuItem item) { - return getSherlock().dispatchOptionsItemSelected(item); - } - - @Override - public void openOptionsMenu() { - if (!getSherlock().dispatchOpenOptionsMenu()) { - super.openOptionsMenu(); - } - } - - @Override - public void closeOptionsMenu() { - if (!getSherlock().dispatchCloseOptionsMenu()) { - super.closeOptionsMenu(); - } - } - - - /////////////////////////////////////////////////////////////////////////// - // Sherlock menu handling - /////////////////////////////////////////////////////////////////////////// - - @Override - public boolean onCreatePanelMenu(int featureId, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onCreateOptionsMenu(menu); - } - return false; - } - - public boolean onCreateOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onPreparePanel(int featureId, View view, Menu menu) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onPrepareOptionsMenu(menu); - } - return false; - } - - public boolean onPrepareOptionsMenu(Menu menu) { - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - if (featureId == Window.FEATURE_OPTIONS_PANEL) { - return onOptionsItemSelected(item); - } - return false; - } - - public boolean onOptionsItemSelected(MenuItem item) { - return false; - } - - - /////////////////////////////////////////////////////////////////////////// - // Content - /////////////////////////////////////////////////////////////////////////// - - @Override - public void addContentView(View view, LayoutParams params) { - getSherlock().addContentView(view, params); - } - - @Override - public void setContentView(int layoutResId) { - getSherlock().setContentView(layoutResId); - } - - @Override - public void setContentView(View view, LayoutParams params) { - getSherlock().setContentView(view, params); - } - - @Override - public void setContentView(View view) { - getSherlock().setContentView(view); - } - - public void requestWindowFeature(long featureId) { - getSherlock().requestFeature((int)featureId); - } - - - /////////////////////////////////////////////////////////////////////////// - // Progress Indication - /////////////////////////////////////////////////////////////////////////// - - public void setSupportProgress(int progress) { - getSherlock().setProgress(progress); - } - - public void setSupportProgressBarIndeterminate(boolean indeterminate) { - getSherlock().setProgressBarIndeterminate(indeterminate); - } - - public void setSupportProgressBarIndeterminateVisibility(boolean visible) { - getSherlock().setProgressBarIndeterminateVisibility(visible); - } - - public void setSupportProgressBarVisibility(boolean visible) { - getSherlock().setProgressBarVisibility(visible); - } - - public void setSupportSecondaryProgress(int secondaryProgress) { - getSherlock().setSecondaryProgress(secondaryProgress); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java deleted file mode 100644 index 5e69275c7..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java +++ /dev/null @@ -1,1203 +0,0 @@ -package com.actionbarsherlock.internal; - -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import org.xmlpull.v1.XmlPullParser; -import android.app.Activity; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.res.AssetManager; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.os.Bundle; -import android.util.AndroidRuntimeException; -import android.util.Log; -import android.util.TypedValue; -import android.view.ContextThemeWrapper; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewStub; -import android.view.Window; -import android.view.accessibility.AccessibilityEvent; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.FrameLayout; -import android.widget.TextView; -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.R; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.internal.app.ActionBarImpl; -import com.actionbarsherlock.internal.view.StandaloneActionMode; -import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; -import com.actionbarsherlock.internal.view.menu.MenuBuilder; -import com.actionbarsherlock.internal.view.menu.MenuItemImpl; -import com.actionbarsherlock.internal.view.menu.MenuPresenter; -import com.actionbarsherlock.internal.widget.ActionBarContainer; -import com.actionbarsherlock.internal.widget.ActionBarContextView; -import com.actionbarsherlock.internal.widget.ActionBarView; -import com.actionbarsherlock.internal.widget.IcsProgressBar; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; - -@ActionBarSherlock.Implementation(api = 7) -public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBuilder.Callback, com.actionbarsherlock.view.Window.Callback, MenuPresenter.Callback, android.view.MenuItem.OnMenuItemClickListener { - /** Window features which are enabled by default. */ - protected static final int DEFAULT_FEATURES = 0; - - static private final String PANELS_TAG = "sherlock:Panels"; - - public ActionBarSherlockCompat(Activity activity, int flags) { - super(activity, flags); - } - - - /////////////////////////////////////////////////////////////////////////// - // Properties - /////////////////////////////////////////////////////////////////////////// - - /** Whether or not the device has a dedicated menu key button. */ - private boolean mReserveOverflow; - /** Lazy-load indicator for {@link #mReserveOverflow}. */ - private boolean mReserveOverflowSet = false; - - /** Current menu instance for managing action items. */ - private MenuBuilder mMenu; - /** Map between native options items and sherlock items. */ - protected HashMap mNativeItemMap; - - /** Parent view of the window decoration (action bar, mode, etc.). */ - private ViewGroup mDecor; - /** Parent view of the activity content. */ - private ViewGroup mContentParent; - - /** Whether or not the title is stable and can be displayed. */ - private boolean mIsTitleReady = false; - /** Whether or not the parent activity has been destroyed. */ - private boolean mIsDestroyed = false; - - /* Emulate PanelFeatureState */ - private boolean mClosingActionMenu; - private boolean mMenuIsPrepared; - private boolean mMenuRefreshContent; - private Bundle mMenuFrozenActionViewState; - - /** Implementation which backs the action bar interface API. */ - private ActionBarImpl aActionBar; - /** Main action bar view which displays the core content. */ - private ActionBarView wActionBar; - /** Relevant window and action bar features flags. */ - private int mFeatures = DEFAULT_FEATURES; - /** Relevant user interface option flags. */ - private int mUiOptions = 0; - - /** Decor indeterminate progress indicator. */ - private IcsProgressBar mCircularProgressBar; - /** Decor progress indicator. */ - private IcsProgressBar mHorizontalProgressBar; - - /** Current displayed context action bar, if any. */ - private ActionMode mActionMode; - /** Parent view in which the context action bar is displayed. */ - private ActionBarContextView mActionModeView; - - /** Title view used with dialogs. */ - private TextView mTitleView; - /** Current activity title. */ - private CharSequence mTitle = null; - /** Whether or not this "activity" is floating (i.e., a dialog) */ - private boolean mIsFloating; - - - - /////////////////////////////////////////////////////////////////////////// - // Instance methods - /////////////////////////////////////////////////////////////////////////// - - @Override - public ActionBar getActionBar() { - if (DEBUG) Log.d(TAG, "[getActionBar]"); - - initActionBar(); - return aActionBar; - } - - private void initActionBar() { - if (DEBUG) Log.d(TAG, "[initActionBar]"); - - // Initializing the window decor can change window feature flags. - // Make sure that we have the correct set before performing the test below. - if (mDecor == null) { - installDecor(); - } - - if ((aActionBar != null) || !hasFeature(Window.FEATURE_ACTION_BAR) || hasFeature(Window.FEATURE_NO_TITLE) || mActivity.isChild()) { - return; - } - - aActionBar = new ActionBarImpl(mActivity, mFeatures); - - if (!mIsDelegate) { - //We may never get another chance to set the title - wActionBar.setWindowTitle(mActivity.getTitle()); - } - } - - @Override - protected Context getThemedContext() { - return aActionBar.getThemedContext(); - } - - @Override - public void setTitle(CharSequence title) { - if (DEBUG) Log.d(TAG, "[setTitle] title: " + title); - - dispatchTitleChanged(title, 0); - } - - @Override - public ActionMode startActionMode(ActionMode.Callback callback) { - if (DEBUG) Log.d(TAG, "[startActionMode] callback: " + callback); - - if (mActionMode != null) { - mActionMode.finish(); - } - - final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); - ActionMode mode = null; - - //Emulate Activity's onWindowStartingActionMode: - initActionBar(); - if (aActionBar != null) { - mode = aActionBar.startActionMode(wrappedCallback); - } - - if (mode != null) { - mActionMode = mode; - } else { - if (mActionModeView == null) { - ViewStub stub = (ViewStub)mDecor.findViewById(R.id.abs__action_mode_bar_stub); - if (stub != null) { - mActionModeView = (ActionBarContextView)stub.inflate(); - } - } - if (mActionModeView != null) { - mActionModeView.killMode(); - mode = new StandaloneActionMode(mActivity, mActionModeView, wrappedCallback, true); - if (callback.onCreateActionMode(mode, mode.getMenu())) { - mode.invalidate(); - mActionModeView.initForMode(mode); - mActionModeView.setVisibility(View.VISIBLE); - mActionMode = mode; - mActionModeView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - } else { - mActionMode = null; - } - } - } - if (mActionMode != null && mActivity instanceof OnActionModeStartedListener) { - ((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode); - } - return mActionMode; - } - - - /////////////////////////////////////////////////////////////////////////// - // Lifecycle and interaction callbacks for delegation - /////////////////////////////////////////////////////////////////////////// - - @Override - public void dispatchConfigurationChanged(Configuration newConfig) { - if (DEBUG) Log.d(TAG, "[dispatchConfigurationChanged] newConfig: " + newConfig); - - if (aActionBar != null) { - aActionBar.onConfigurationChanged(newConfig); - } - } - - @Override - public void dispatchPostResume() { - if (DEBUG) Log.d(TAG, "[dispatchPostResume]"); - - if (aActionBar != null) { - aActionBar.setShowHideAnimationEnabled(true); - } - } - - @Override - public void dispatchPause() { - if (DEBUG) Log.d(TAG, "[dispatchPause]"); - - if (wActionBar != null && wActionBar.isOverflowMenuShowing()) { - wActionBar.hideOverflowMenu(); - } - } - - @Override - public void dispatchStop() { - if (DEBUG) Log.d(TAG, "[dispatchStop]"); - - if (aActionBar != null) { - aActionBar.setShowHideAnimationEnabled(false); - } - } - - @Override - public void dispatchInvalidateOptionsMenu() { - if (DEBUG) Log.d(TAG, "[dispatchInvalidateOptionsMenu]"); - - Bundle savedActionViewStates = null; - if (mMenu != null) { - savedActionViewStates = new Bundle(); - mMenu.saveActionViewStates(savedActionViewStates); - if (savedActionViewStates.size() > 0) { - mMenuFrozenActionViewState = savedActionViewStates; - } - // This will be started again when the panel is prepared. - mMenu.stopDispatchingItemsChanged(); - mMenu.clear(); - } - mMenuRefreshContent = true; - - // Prepare the options panel if we have an action bar - if (wActionBar != null) { - mMenuIsPrepared = false; - preparePanel(); - } - } - - @Override - public boolean dispatchOpenOptionsMenu() { - if (DEBUG) Log.d(TAG, "[dispatchOpenOptionsMenu]"); - - if (!isReservingOverflow()) { - return false; - } - - return wActionBar.showOverflowMenu(); - } - - @Override - public boolean dispatchCloseOptionsMenu() { - if (DEBUG) Log.d(TAG, "[dispatchCloseOptionsMenu]"); - - if (!isReservingOverflow()) { - return false; - } - - if (wActionBar != null) { - return wActionBar.hideOverflowMenu(); - } - return false; - } - - @Override - public void dispatchPostCreate(Bundle savedInstanceState) { - if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); - - if (mIsDelegate) { - mIsTitleReady = true; - } - - if (mDecor == null) { - initActionBar(); - } - } - - @Override - public boolean dispatchCreateOptionsMenu(android.view.Menu menu) { - if (DEBUG) { - Log.d(TAG, "[dispatchCreateOptionsMenu] android.view.Menu: " + menu); - Log.d(TAG, "[dispatchCreateOptionsMenu] returning true"); - } - return true; - } - - @Override - public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) { - if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] android.view.Menu: " + menu); - - if (mActionMode != null) { - return false; - } - - mMenuIsPrepared = false; - if (!preparePanel()) { - return false; - } - - if (isReservingOverflow()) { - return false; - } - - if (mNativeItemMap == null) { - mNativeItemMap = new HashMap(); - } else { - mNativeItemMap.clear(); - } - - if (mMenu == null) { - return false; - } - - boolean result = mMenu.bindNativeOverflow(menu, this, mNativeItemMap); - if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] returning " + result); - return result; - } - - @Override - public boolean dispatchOptionsItemSelected(android.view.MenuItem item) { - throw new IllegalStateException("Native callback invoked. Create a test case and report!"); - } - - @Override - public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) { - if (DEBUG) Log.d(TAG, "[dispatchMenuOpened] featureId: " + featureId + ", menu: " + menu); - - if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) { - if (aActionBar != null) { - aActionBar.dispatchMenuVisibilityChanged(true); - } - return true; - } - - return false; - } - - @Override - public void dispatchPanelClosed(int featureId, android.view.Menu menu){ - if (DEBUG) Log.d(TAG, "[dispatchPanelClosed] featureId: " + featureId + ", menu: " + menu); - - if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) { - if (aActionBar != null) { - aActionBar.dispatchMenuVisibilityChanged(false); - } - } - } - - @Override - public void dispatchTitleChanged(CharSequence title, int color) { - if (DEBUG) Log.d(TAG, "[dispatchTitleChanged] title: " + title + ", color: " + color); - - if (!mIsDelegate || mIsTitleReady) { - if (mTitleView != null) { - mTitleView.setText(title); - } else if (wActionBar != null) { - wActionBar.setWindowTitle(title); - } - } - - mTitle = title; - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] event: " + event); - - final int keyCode = event.getKeyCode(); - - // Not handled by the view hierarchy, does the action bar want it - // to cancel out of something special? - if (keyCode == KeyEvent.KEYCODE_BACK) { - final int action = event.getAction(); - // Back cancels action modes first. - if (mActionMode != null) { - if (action == KeyEvent.ACTION_UP) { - mActionMode.finish(); - } - if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); - return true; - } - - // Next collapse any expanded action views. - if (wActionBar != null && wActionBar.hasExpandedActionView()) { - if (action == KeyEvent.ACTION_UP) { - wActionBar.collapseActionView(); - } - if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); - return true; - } - } - - if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); - return false; - } - - @Override - public void dispatchDestroy() { - mIsDestroyed = true; - } - - @Override - public void dispatchSaveInstanceState(Bundle outState) { - if (mMenu != null) { - mMenuFrozenActionViewState = new Bundle(); - mMenu.saveActionViewStates(mMenuFrozenActionViewState); - } - outState.putParcelable(PANELS_TAG, mMenuFrozenActionViewState); - } - - @Override - public void dispatchRestoreInstanceState(Bundle savedInstanceState) { - mMenuFrozenActionViewState = savedInstanceState.getParcelable(PANELS_TAG); - } - - /////////////////////////////////////////////////////////////////////////// - // Menu callback lifecycle and creation - /////////////////////////////////////////////////////////////////////////// - - private boolean preparePanel() { - // Already prepared (isPrepared will be reset to false later) - if (mMenuIsPrepared) { - return true; - } - - // Init the panel state's menu--return false if init failed - if (mMenu == null || mMenuRefreshContent) { - if (mMenu == null) { - if (!initializePanelMenu() || (mMenu == null)) { - return false; - } - } - - if (wActionBar != null) { - wActionBar.setMenu(mMenu, this); - } - - // Call callback, and return if it doesn't want to display menu. - - // Creating the panel menu will involve a lot of manipulation; - // don't dispatch change events to presenters until we're done. - mMenu.stopDispatchingItemsChanged(); - if (!callbackCreateOptionsMenu(mMenu)) { - // Ditch the menu created above - mMenu = null; - - if (wActionBar != null) { - // Don't show it in the action bar either - wActionBar.setMenu(null, this); - } - - return false; - } - - mMenuRefreshContent = false; - } - - // Callback and return if the callback does not want to show the menu - - // Preparing the panel menu can involve a lot of manipulation; - // don't dispatch change events to presenters until we're done. - mMenu.stopDispatchingItemsChanged(); - - // Restore action view state before we prepare. This gives apps - // an opportunity to override frozen/restored state in onPrepare. - if (mMenuFrozenActionViewState != null) { - mMenu.restoreActionViewStates(mMenuFrozenActionViewState); - mMenuFrozenActionViewState = null; - } - - if (!callbackPrepareOptionsMenu(mMenu)) { - if (wActionBar != null) { - // The app didn't want to show the menu for now but it still exists. - // Clear it out of the action bar. - wActionBar.setMenu(null, this); - } - mMenu.startDispatchingItemsChanged(); - return false; - } - - // Set the proper keymap - KeyCharacterMap kmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); - mMenu.setQwertyMode(kmap.getKeyboardType() != KeyCharacterMap.NUMERIC); - mMenu.startDispatchingItemsChanged(); - - // Set other state - mMenuIsPrepared = true; - - return true; - } - - public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { - return callbackOptionsItemSelected(item); - } - - public void onMenuModeChange(MenuBuilder menu) { - reopenMenu(true); - } - - private void reopenMenu(boolean toggleMenuMode) { - if (wActionBar != null && wActionBar.isOverflowReserved()) { - if (!wActionBar.isOverflowMenuShowing() || !toggleMenuMode) { - if (wActionBar.getVisibility() == View.VISIBLE) { - if (callbackPrepareOptionsMenu(mMenu)) { - wActionBar.showOverflowMenu(); - } - } - } else { - wActionBar.hideOverflowMenu(); - } - return; - } - } - - private boolean initializePanelMenu() { - Context context = mActivity;//getContext(); - - // If we have an action bar, initialize the menu with a context themed for it. - if (wActionBar != null) { - TypedValue outValue = new TypedValue(); - Resources.Theme currentTheme = context.getTheme(); - currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme, - outValue, true); - final int targetThemeRes = outValue.resourceId; - - if (targetThemeRes != 0 /*&& context.getThemeResId() != targetThemeRes*/) { - context = new ContextThemeWrapper(context, targetThemeRes); - } - } - - mMenu = new MenuBuilder(context); - mMenu.setCallback(this); - - return true; - } - - void checkCloseActionMenu(Menu menu) { - if (mClosingActionMenu) { - return; - } - - mClosingActionMenu = true; - wActionBar.dismissPopupMenus(); - //Callback cb = getCallback(); - //if (cb != null && !isDestroyed()) { - // cb.onPanelClosed(FEATURE_ACTION_BAR, menu); - //} - mClosingActionMenu = false; - } - - @Override - public boolean onOpenSubMenu(MenuBuilder subMenu) { - return true; - } - - @Override - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - checkCloseActionMenu(menu); - } - - @Override - public boolean onMenuItemClick(android.view.MenuItem item) { - if (DEBUG) Log.d(TAG, "[mNativeItemListener.onMenuItemClick] item: " + item); - - final MenuItemImpl sherlockItem = mNativeItemMap.get(item); - if (sherlockItem != null) { - sherlockItem.invoke(); - } else { - Log.e(TAG, "Options item \"" + item + "\" not found in mapping"); - } - - return true; //Do not allow continuation of native handling - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - return callbackOptionsItemSelected(item); - } - - - /////////////////////////////////////////////////////////////////////////// - // Progress bar interaction and internal handling - /////////////////////////////////////////////////////////////////////////// - - @Override - public void setProgressBarVisibility(boolean visible) { - if (DEBUG) Log.d(TAG, "[setProgressBarVisibility] visible: " + visible); - - setFeatureInt(Window.FEATURE_PROGRESS, visible ? Window.PROGRESS_VISIBILITY_ON : - Window.PROGRESS_VISIBILITY_OFF); - } - - @Override - public void setProgressBarIndeterminateVisibility(boolean visible) { - if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminateVisibility] visible: " + visible); - - setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, - visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF); - } - - @Override - public void setProgressBarIndeterminate(boolean indeterminate) { - if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminate] indeterminate: " + indeterminate); - - setFeatureInt(Window.FEATURE_PROGRESS, - indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF); - } - - @Override - public void setProgress(int progress) { - if (DEBUG) Log.d(TAG, "[setProgress] progress: " + progress); - - setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START); - } - - @Override - public void setSecondaryProgress(int secondaryProgress) { - if (DEBUG) Log.d(TAG, "[setSecondaryProgress] secondaryProgress: " + secondaryProgress); - - setFeatureInt(Window.FEATURE_PROGRESS, - secondaryProgress + Window.PROGRESS_SECONDARY_START); - } - - private void setFeatureInt(int featureId, int value) { - updateInt(featureId, value, false); - } - - private void updateInt(int featureId, int value, boolean fromResume) { - // Do nothing if the decor is not yet installed... an update will - // need to be forced when we eventually become active. - if (mContentParent == null) { - return; - } - - final int featureMask = 1 << featureId; - - if ((getFeatures() & featureMask) == 0 && !fromResume) { - return; - } - - onIntChanged(featureId, value); - } - - private void onIntChanged(int featureId, int value) { - if (featureId == Window.FEATURE_PROGRESS || featureId == Window.FEATURE_INDETERMINATE_PROGRESS) { - updateProgressBars(value); - } - } - - private void updateProgressBars(int value) { - IcsProgressBar circularProgressBar = getCircularProgressBar(true); - IcsProgressBar horizontalProgressBar = getHorizontalProgressBar(true); - - final int features = mFeatures;//getLocalFeatures(); - if (value == Window.PROGRESS_VISIBILITY_ON) { - if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) { - int level = horizontalProgressBar.getProgress(); - int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ? - View.VISIBLE : View.INVISIBLE; - horizontalProgressBar.setVisibility(visibility); - } - if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) { - circularProgressBar.setVisibility(View.VISIBLE); - } - } else if (value == Window.PROGRESS_VISIBILITY_OFF) { - if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) { - horizontalProgressBar.setVisibility(View.GONE); - } - if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) { - circularProgressBar.setVisibility(View.GONE); - } - } else if (value == Window.PROGRESS_INDETERMINATE_ON) { - horizontalProgressBar.setIndeterminate(true); - } else if (value == Window.PROGRESS_INDETERMINATE_OFF) { - horizontalProgressBar.setIndeterminate(false); - } else if (Window.PROGRESS_START <= value && value <= Window.PROGRESS_END) { - // We want to set the progress value before testing for visibility - // so that when the progress bar becomes visible again, it has the - // correct level. - horizontalProgressBar.setProgress(value - Window.PROGRESS_START); - - if (value < Window.PROGRESS_END) { - showProgressBars(horizontalProgressBar, circularProgressBar); - } else { - hideProgressBars(horizontalProgressBar, circularProgressBar); - } - } else if (Window.PROGRESS_SECONDARY_START <= value && value <= Window.PROGRESS_SECONDARY_END) { - horizontalProgressBar.setSecondaryProgress(value - Window.PROGRESS_SECONDARY_START); - - showProgressBars(horizontalProgressBar, circularProgressBar); - } - } - - private void showProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) { - final int features = mFeatures;//getLocalFeatures(); - if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 && - spinnyProgressBar.getVisibility() == View.INVISIBLE) { - spinnyProgressBar.setVisibility(View.VISIBLE); - } - // Only show the progress bars if the primary progress is not complete - if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 && - horizontalProgressBar.getProgress() < 10000) { - horizontalProgressBar.setVisibility(View.VISIBLE); - } - } - - private void hideProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) { - final int features = mFeatures;//getLocalFeatures(); - Animation anim = AnimationUtils.loadAnimation(mActivity, android.R.anim.fade_out); - anim.setDuration(1000); - if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 && - spinnyProgressBar.getVisibility() == View.VISIBLE) { - spinnyProgressBar.startAnimation(anim); - spinnyProgressBar.setVisibility(View.INVISIBLE); - } - if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 && - horizontalProgressBar.getVisibility() == View.VISIBLE) { - horizontalProgressBar.startAnimation(anim); - horizontalProgressBar.setVisibility(View.INVISIBLE); - } - } - - private IcsProgressBar getCircularProgressBar(boolean shouldInstallDecor) { - if (mCircularProgressBar != null) { - return mCircularProgressBar; - } - if (mContentParent == null && shouldInstallDecor) { - installDecor(); - } - mCircularProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_circular); - if (mCircularProgressBar != null) { - mCircularProgressBar.setVisibility(View.INVISIBLE); - } - return mCircularProgressBar; - } - - private IcsProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) { - if (mHorizontalProgressBar != null) { - return mHorizontalProgressBar; - } - if (mContentParent == null && shouldInstallDecor) { - installDecor(); - } - mHorizontalProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_horizontal); - if (mHorizontalProgressBar != null) { - mHorizontalProgressBar.setVisibility(View.INVISIBLE); - } - return mHorizontalProgressBar; - } - - - /////////////////////////////////////////////////////////////////////////// - // Feature management and content interaction and creation - /////////////////////////////////////////////////////////////////////////// - - private int getFeatures() { - if (DEBUG) Log.d(TAG, "[getFeatures] returning " + mFeatures); - - return mFeatures; - } - - @Override - public boolean hasFeature(int featureId) { - if (DEBUG) Log.d(TAG, "[hasFeature] featureId: " + featureId); - - boolean result = (mFeatures & (1 << featureId)) != 0; - if (DEBUG) Log.d(TAG, "[hasFeature] returning " + result); - return result; - } - - @Override - public boolean requestFeature(int featureId) { - if (DEBUG) Log.d(TAG, "[requestFeature] featureId: " + featureId); - - if (mContentParent != null) { - throw new AndroidRuntimeException("requestFeature() must be called before adding content"); - } - - switch (featureId) { - case Window.FEATURE_ACTION_BAR: - case Window.FEATURE_ACTION_BAR_OVERLAY: - case Window.FEATURE_ACTION_MODE_OVERLAY: - case Window.FEATURE_INDETERMINATE_PROGRESS: - case Window.FEATURE_NO_TITLE: - case Window.FEATURE_PROGRESS: - mFeatures |= (1 << featureId); - return true; - - default: - return false; - } - } - - @Override - public void setUiOptions(int uiOptions) { - if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions); - - mUiOptions = uiOptions; - } - - @Override - public void setUiOptions(int uiOptions, int mask) { - if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions + ", mask: " + mask); - - mUiOptions = (mUiOptions & ~mask) | (uiOptions & mask); - } - - @Override - public void setContentView(int layoutResId) { - if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId); - - if (mContentParent == null) { - installDecor(); - } else { - mContentParent.removeAllViews(); - } - mActivity.getLayoutInflater().inflate(layoutResId, mContentParent); - - android.view.Window.Callback callback = mActivity.getWindow().getCallback(); - if (callback != null) { - callback.onContentChanged(); - } - - initActionBar(); - } - - @Override - public void setContentView(View view, ViewGroup.LayoutParams params) { - if (DEBUG) Log.d(TAG, "[setContentView] view: " + view + ", params: " + params); - - if (mContentParent == null) { - installDecor(); - } else { - mContentParent.removeAllViews(); - } - mContentParent.addView(view, params); - - android.view.Window.Callback callback = mActivity.getWindow().getCallback(); - if (callback != null) { - callback.onContentChanged(); - } - - initActionBar(); - } - - @Override - public void addContentView(View view, ViewGroup.LayoutParams params) { - if (DEBUG) Log.d(TAG, "[addContentView] view: " + view + ", params: " + params); - - if (mContentParent == null) { - installDecor(); - } - mContentParent.addView(view, params); - - initActionBar(); - } - - private void installDecor() { - if (DEBUG) Log.d(TAG, "[installDecor]"); - - if (mDecor == null) { - mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); - } - if (mContentParent == null) { - //Since we are not operating at the window level we need to take - //into account the fact that the true decor may have already been - //initialized and had content attached to it. If that is the case, - //copy over its children to our new content container. - List views = null; - if (mDecor.getChildCount() > 0) { - views = new ArrayList(1); //Usually there's only one child - for (int i = 0, children = mDecor.getChildCount(); i < children; i++) { - View child = mDecor.getChildAt(0); - mDecor.removeView(child); - views.add(child); - } - } - - mContentParent = generateLayout(); - - //Copy over the old children. See above for explanation. - if (views != null) { - for (View child : views) { - mContentParent.addView(child); - } - } - - mTitleView = (TextView)mDecor.findViewById(android.R.id.title); - if (mTitleView != null) { - if (hasFeature(Window.FEATURE_NO_TITLE)) { - mTitleView.setVisibility(View.GONE); - if (mContentParent instanceof FrameLayout) { - ((FrameLayout)mContentParent).setForeground(null); - } - } else { - mTitleView.setText(mTitle); - } - } else { - wActionBar = (ActionBarView)mDecor.findViewById(R.id.abs__action_bar); - if (wActionBar != null) { - wActionBar.setWindowCallback(this); - if (wActionBar.getTitle() == null) { - wActionBar.setWindowTitle(mActivity.getTitle()); - } - if (hasFeature(Window.FEATURE_PROGRESS)) { - wActionBar.initProgress(); - } - if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) { - wActionBar.initIndeterminateProgress(); - } - - //Since we don't require onCreate dispatching, parse for uiOptions here - int uiOptions = loadUiOptionsFromManifest(mActivity); - if (uiOptions != 0) { - mUiOptions = uiOptions; - } - - boolean splitActionBar = false; - final boolean splitWhenNarrow = (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0; - if (splitWhenNarrow) { - splitActionBar = getResources_getBoolean(mActivity, R.bool.abs__split_action_bar_is_narrow); - } else { - splitActionBar = mActivity.getTheme() - .obtainStyledAttributes(R.styleable.SherlockTheme) - .getBoolean(R.styleable.SherlockTheme_windowSplitActionBar, false); - } - final ActionBarContainer splitView = (ActionBarContainer)mDecor.findViewById(R.id.abs__split_action_bar); - if (splitView != null) { - wActionBar.setSplitView(splitView); - wActionBar.setSplitActionBar(splitActionBar); - wActionBar.setSplitWhenNarrow(splitWhenNarrow); - - mActionModeView = (ActionBarContextView)mDecor.findViewById(R.id.abs__action_context_bar); - mActionModeView.setSplitView(splitView); - mActionModeView.setSplitActionBar(splitActionBar); - mActionModeView.setSplitWhenNarrow(splitWhenNarrow); - } else if (splitActionBar) { - Log.e(TAG, "Requested split action bar with incompatible window decor! Ignoring request."); - } - - // Post the panel invalidate for later; avoid application onCreateOptionsMenu - // being called in the middle of onCreate or similar. - mDecor.post(new Runnable() { - @Override - public void run() { - //Invalidate if the panel menu hasn't been created before this. - if (!mIsDestroyed && !mActivity.isFinishing() && mMenu == null) { - dispatchInvalidateOptionsMenu(); - } - } - }); - } - } - } - } - - private ViewGroup generateLayout() { - if (DEBUG) Log.d(TAG, "[generateLayout]"); - - // Apply data from current theme. - - TypedArray a = mActivity.getTheme().obtainStyledAttributes(R.styleable.SherlockTheme); - - mIsFloating = a.getBoolean(R.styleable.SherlockTheme_android_windowIsFloating, false); - - if (!a.hasValue(R.styleable.SherlockTheme_windowActionBar)) { - throw new IllegalStateException("You must use Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.Light.DarkActionBar, or a derivative."); - } - - if (a.getBoolean(R.styleable.SherlockTheme_windowNoTitle, false)) { - requestFeature(Window.FEATURE_NO_TITLE); - } else if (a.getBoolean(R.styleable.SherlockTheme_windowActionBar, false)) { - // Don't allow an action bar if there is no title. - requestFeature(Window.FEATURE_ACTION_BAR); - } - - if (a.getBoolean(R.styleable.SherlockTheme_windowActionBarOverlay, false)) { - requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - } - - if (a.getBoolean(R.styleable.SherlockTheme_windowActionModeOverlay, false)) { - requestFeature(Window.FEATURE_ACTION_MODE_OVERLAY); - } - - a.recycle(); - - int layoutResource; - if (!hasFeature(Window.FEATURE_NO_TITLE)) { - if (mIsFloating) { - //Trash original dialog LinearLayout - mDecor = (ViewGroup)mDecor.getParent(); - mDecor.removeAllViews(); - - layoutResource = R.layout.abs__dialog_title_holo; - } else { - if (hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) { - layoutResource = R.layout.abs__screen_action_bar_overlay; - } else { - layoutResource = R.layout.abs__screen_action_bar; - } - } - } else if (hasFeature(Window.FEATURE_ACTION_MODE_OVERLAY) && !hasFeature(Window.FEATURE_NO_TITLE)) { - layoutResource = R.layout.abs__screen_simple_overlay_action_mode; - } else { - layoutResource = R.layout.abs__screen_simple; - } - - if (DEBUG) Log.d(TAG, "[generateLayout] using screen XML " + mActivity.getResources().getString(layoutResource)); - View in = mActivity.getLayoutInflater().inflate(layoutResource, null); - mDecor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); - - ViewGroup contentParent = (ViewGroup)mDecor.findViewById(R.id.abs__content); - if (contentParent == null) { - throw new RuntimeException("Couldn't find content container view"); - } - - //Make our new child the true content view (for fragments). VERY VOLATILE! - mDecor.setId(View.NO_ID); - contentParent.setId(android.R.id.content); - - if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) { - IcsProgressBar progress = getCircularProgressBar(false); - if (progress != null) { - progress.setIndeterminate(true); - } - } - - return contentParent; - } - - - /////////////////////////////////////////////////////////////////////////// - // Miscellaneous - /////////////////////////////////////////////////////////////////////////// - - /** - * Determine whether or not the device has a dedicated menu key. - * - * @return {@code true} if native menu key is present. - */ - private boolean isReservingOverflow() { - if (!mReserveOverflowSet) { - mReserveOverflow = ActionMenuPresenter.reserveOverflow(mActivity); - mReserveOverflowSet = true; - } - return mReserveOverflow; - } - - private static int loadUiOptionsFromManifest(Activity activity) { - int uiOptions = 0; - try { - final String thisPackage = activity.getClass().getName(); - if (DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage); - - final String packageName = activity.getApplicationInfo().packageName; - final AssetManager am = activity.createPackageContext(packageName, 0).getAssets(); - final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml"); - - int eventType = xml.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - String name = xml.getName(); - - if ("application".equals(name)) { - //Check if the has the attribute - if (DEBUG) Log.d(TAG, "Got "); - - for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { - if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); - - if ("uiOptions".equals(xml.getAttributeName(i))) { - uiOptions = xml.getAttributeIntValue(i, 0); - break; //out of for loop - } - } - } else if ("activity".equals(name)) { - //Check if the is us and has the attribute - if (DEBUG) Log.d(TAG, "Got "); - Integer activityUiOptions = null; - String activityPackage = null; - boolean isOurActivity = false; - - for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { - if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); - - //We need both uiOptions and name attributes - String attrName = xml.getAttributeName(i); - if ("uiOptions".equals(attrName)) { - activityUiOptions = xml.getAttributeIntValue(i, 0); - } else if ("name".equals(attrName)) { - activityPackage = cleanActivityName(packageName, xml.getAttributeValue(i)); - if (!thisPackage.equals(activityPackage)) { - break; //out of for loop - } - isOurActivity = true; - } - - //Make sure we have both attributes before processing - if ((activityUiOptions != null) && (activityPackage != null)) { - //Our activity, uiOptions specified, override with our value - uiOptions = activityUiOptions.intValue(); - } - } - if (isOurActivity) { - //If we matched our activity but it had no logo don't - //do any more processing of the manifest - break; - } - } - } - eventType = xml.nextToken(); - } - } catch (Exception e) { - e.printStackTrace(); - } - if (DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(uiOptions)); - return uiOptions; - } - - public static String cleanActivityName(String manifestPackage, String activityName) { - if (activityName.charAt(0) == '.') { - //Relative activity name (e.g., android:name=".ui.SomeClass") - return manifestPackage + activityName; - } - if (activityName.indexOf('.', 1) == -1) { - //Unqualified activity name (e.g., android:name="SomeClass") - return manifestPackage + "." + activityName; - } - //Fully-qualified activity name (e.g., "com.my.package.SomeClass") - return activityName; - } - - /** - * Clears out internal reference when the action mode is destroyed. - */ - private class ActionModeCallbackWrapper implements ActionMode.Callback { - private final ActionMode.Callback mWrapped; - - public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { - mWrapped = wrapped; - } - - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - return mWrapped.onCreateActionMode(mode, menu); - } - - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return mWrapped.onPrepareActionMode(mode, menu); - } - - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - return mWrapped.onActionItemClicked(mode, item); - } - - public void onDestroyActionMode(ActionMode mode) { - mWrapped.onDestroyActionMode(mode); - if (mActionModeView != null) { - mActionModeView.setVisibility(View.GONE); - mActionModeView.removeAllViews(); - } - if (mActivity instanceof OnActionModeFinishedListener) { - ((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode); - } - mActionMode = null; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java deleted file mode 100644 index 0824d3848..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java +++ /dev/null @@ -1,336 +0,0 @@ -package com.actionbarsherlock.internal; - -import com.actionbarsherlock.ActionBarSherlock; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.internal.app.ActionBarWrapper; -import com.actionbarsherlock.internal.view.menu.MenuWrapper; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.MenuInflater; -import android.app.Activity; -import android.content.Context; -import android.util.Log; -import android.util.TypedValue; -import android.view.ContextThemeWrapper; -import android.view.View; -import android.view.Window; -import android.view.ViewGroup.LayoutParams; - -@ActionBarSherlock.Implementation(api = 14) -public class ActionBarSherlockNative extends ActionBarSherlock { - private ActionBarWrapper mActionBar; - private ActionModeWrapper mActionMode; - private MenuWrapper mMenu; - - public ActionBarSherlockNative(Activity activity, int flags) { - super(activity, flags); - } - - - @Override - public ActionBar getActionBar() { - if (DEBUG) Log.d(TAG, "[getActionBar]"); - - initActionBar(); - return mActionBar; - } - - private void initActionBar() { - if (mActionBar != null || mActivity.getActionBar() == null) { - return; - } - - mActionBar = new ActionBarWrapper(mActivity); - } - - @Override - public void dispatchInvalidateOptionsMenu() { - if (DEBUG) Log.d(TAG, "[dispatchInvalidateOptionsMenu]"); - - mActivity.getWindow().invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL); - } - - @Override - public boolean dispatchCreateOptionsMenu(android.view.Menu menu) { - if (DEBUG) Log.d(TAG, "[dispatchCreateOptionsMenu] menu: " + menu); - - if (mMenu == null || menu != mMenu.unwrap()) { - mMenu = new MenuWrapper(menu); - } - - final boolean result = callbackCreateOptionsMenu(mMenu); - if (DEBUG) Log.d(TAG, "[dispatchCreateOptionsMenu] returning " + result); - return result; - } - - @Override - public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) { - if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] menu: " + menu); - - final boolean result = callbackPrepareOptionsMenu(mMenu); - if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] returning " + result); - return result; - } - - @Override - public boolean dispatchOptionsItemSelected(android.view.MenuItem item) { - if (DEBUG) Log.d(TAG, "[dispatchOptionsItemSelected] item: " + item.getTitleCondensed()); - - final boolean result = callbackOptionsItemSelected(mMenu.findItem(item)); - if (DEBUG) Log.d(TAG, "[dispatchOptionsItemSelected] returning " + result); - return result; - } - - @Override - public boolean hasFeature(int feature) { - if (DEBUG) Log.d(TAG, "[hasFeature] feature: " + feature); - - final boolean result = mActivity.getWindow().hasFeature(feature); - if (DEBUG) Log.d(TAG, "[hasFeature] returning " + result); - return result; - } - - @Override - public boolean requestFeature(int featureId) { - if (DEBUG) Log.d(TAG, "[requestFeature] featureId: " + featureId); - - final boolean result = mActivity.getWindow().requestFeature(featureId); - if (DEBUG) Log.d(TAG, "[requestFeature] returning " + result); - return result; - } - - @Override - public void setUiOptions(int uiOptions) { - if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions); - - mActivity.getWindow().setUiOptions(uiOptions); - } - - @Override - public void setUiOptions(int uiOptions, int mask) { - if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions + ", mask: " + mask); - - mActivity.getWindow().setUiOptions(uiOptions, mask); - } - - @Override - public void setContentView(int layoutResId) { - if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId); - - mActivity.getWindow().setContentView(layoutResId); - initActionBar(); - } - - @Override - public void setContentView(View view, LayoutParams params) { - if (DEBUG) Log.d(TAG, "[setContentView] view: " + view + ", params: " + params); - - mActivity.getWindow().setContentView(view, params); - initActionBar(); - } - - @Override - public void addContentView(View view, LayoutParams params) { - if (DEBUG) Log.d(TAG, "[addContentView] view: " + view + ", params: " + params); - - mActivity.getWindow().addContentView(view, params); - initActionBar(); - } - - @Override - public void setTitle(CharSequence title) { - if (DEBUG) Log.d(TAG, "[setTitle] title: " + title); - - mActivity.getWindow().setTitle(title); - } - - @Override - public void setProgressBarVisibility(boolean visible) { - if (DEBUG) Log.d(TAG, "[setProgressBarVisibility] visible: " + visible); - - mActivity.setProgressBarVisibility(visible); - } - - @Override - public void setProgressBarIndeterminateVisibility(boolean visible) { - if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminateVisibility] visible: " + visible); - - mActivity.setProgressBarIndeterminateVisibility(visible); - } - - @Override - public void setProgressBarIndeterminate(boolean indeterminate) { - if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminate] indeterminate: " + indeterminate); - - mActivity.setProgressBarIndeterminate(indeterminate); - } - - @Override - public void setProgress(int progress) { - if (DEBUG) Log.d(TAG, "[setProgress] progress: " + progress); - - mActivity.setProgress(progress); - } - - @Override - public void setSecondaryProgress(int secondaryProgress) { - if (DEBUG) Log.d(TAG, "[setSecondaryProgress] secondaryProgress: " + secondaryProgress); - - mActivity.setSecondaryProgress(secondaryProgress); - } - - @Override - protected Context getThemedContext() { - Context context = mActivity; - TypedValue outValue = new TypedValue(); - mActivity.getTheme().resolveAttribute(android.R.attr.actionBarWidgetTheme, outValue, true); - if (outValue.resourceId != 0) { - //We are unable to test if this is the same as our current theme - //so we just wrap it and hope that if the attribute was specified - //then the user is intentionally specifying an alternate theme. - context = new ContextThemeWrapper(context, outValue.resourceId); - } - return context; - } - - @Override - public ActionMode startActionMode(com.actionbarsherlock.view.ActionMode.Callback callback) { - if (DEBUG) Log.d(TAG, "[startActionMode] callback: " + callback); - - if (mActionMode != null) { - mActionMode.finish(); - } - ActionModeCallbackWrapper wrapped = null; - if (callback != null) { - wrapped = new ActionModeCallbackWrapper(callback); - } - - //Calling this will trigger the callback wrapper's onCreate which - //is where we will set the new instance to mActionMode since we need - //to pass it through to the sherlock callbacks and the call below - //will not have returned yet to store its value. - if (mActivity.startActionMode(wrapped) == null) { - mActionMode = null; - } - if (mActivity instanceof OnActionModeStartedListener && mActionMode != null) { - ((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode); - } - - return mActionMode; - } - - private class ActionModeCallbackWrapper implements android.view.ActionMode.Callback { - private final ActionMode.Callback mCallback; - - public ActionModeCallbackWrapper(ActionMode.Callback callback) { - mCallback = callback; - } - - @Override - public boolean onCreateActionMode(android.view.ActionMode mode, android.view.Menu menu) { - //See ActionBarSherlockNative#startActionMode - mActionMode = new ActionModeWrapper(mode); - - return mCallback.onCreateActionMode(mActionMode, mActionMode.getMenu()); - } - - @Override - public boolean onPrepareActionMode(android.view.ActionMode mode, android.view.Menu menu) { - return mCallback.onPrepareActionMode(mActionMode, mActionMode.getMenu()); - } - - @Override - public boolean onActionItemClicked(android.view.ActionMode mode, android.view.MenuItem item) { - return mCallback.onActionItemClicked(mActionMode, mActionMode.getMenu().findItem(item)); - } - - @Override - public void onDestroyActionMode(android.view.ActionMode mode) { - mCallback.onDestroyActionMode(mActionMode); - if (mActivity instanceof OnActionModeFinishedListener) { - ((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode); - } - } - } - - private class ActionModeWrapper extends ActionMode { - private final android.view.ActionMode mActionMode; - private MenuWrapper mMenu = null; - - ActionModeWrapper(android.view.ActionMode actionMode) { - mActionMode = actionMode; - } - - @Override - public void setTitle(CharSequence title) { - mActionMode.setTitle(title); - } - - @Override - public void setTitle(int resId) { - mActionMode.setTitle(resId); - } - - @Override - public void setSubtitle(CharSequence subtitle) { - mActionMode.setSubtitle(subtitle); - } - - @Override - public void setSubtitle(int resId) { - mActionMode.setSubtitle(resId); - } - - @Override - public void setCustomView(View view) { - mActionMode.setCustomView(view); - } - - @Override - public void invalidate() { - mActionMode.invalidate(); - } - - @Override - public void finish() { - mActionMode.finish(); - } - - @Override - public MenuWrapper getMenu() { - if (mMenu == null) { - mMenu = new MenuWrapper(mActionMode.getMenu()); - } - return mMenu; - } - - @Override - public CharSequence getTitle() { - return mActionMode.getTitle(); - } - - @Override - public CharSequence getSubtitle() { - return mActionMode.getSubtitle(); - } - - @Override - public View getCustomView() { - return mActionMode.getCustomView(); - } - - @Override - public MenuInflater getMenuInflater() { - return ActionBarSherlockNative.this.getMenuInflater(); - } - - @Override - public void setTag(Object tag) { - mActionMode.setTag(tag); - } - - @Override - public Object getTag() { - return mActionMode.getTag(); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java deleted file mode 100644 index 8e1efe8c5..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.actionbarsherlock.internal; - -import android.content.Context; -import android.os.Build; -import android.util.DisplayMetrics; -import com.actionbarsherlock.R; - -public final class ResourcesCompat { - //No instances - private ResourcesCompat() {} - - - /** - * Support implementation of {@code getResources().getBoolean()} that we - * can use to simulate filtering based on width and smallest width - * qualifiers on pre-3.2. - * - * @param context Context to load booleans from on 3.2+ and to fetch the - * display metrics. - * @param id Id of boolean to load. - * @return Associated boolean value as reflected by the current display - * metrics. - */ - public static boolean getResources_getBoolean(Context context, int id) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - return context.getResources().getBoolean(id); - } - - DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - float widthDp = metrics.widthPixels / metrics.density; - float heightDp = metrics.heightPixels / metrics.density; - float smallestWidthDp = (widthDp < heightDp) ? widthDp : heightDp; - - if (id == R.bool.abs__action_bar_embed_tabs) { - if (widthDp >= 480) { - return true; //values-w480dp - } - return false; //values - } - if (id == R.bool.abs__split_action_bar_is_narrow) { - if (widthDp >= 480) { - return false; //values-w480dp - } - return true; //values - } - if (id == R.bool.abs__action_bar_expanded_action_views_exclusive) { - if (smallestWidthDp >= 600) { - return false; //values-sw600dp - } - return true; //values - } - if (id == R.bool.abs__config_allowActionMenuItemTextWithIcon) { - if (widthDp >= 480) { - return true; //values-w480dp - } - return false; //values - } - - throw new IllegalArgumentException("Unknown boolean resource ID " + id); - } - - /** - * Support implementation of {@code getResources().getInteger()} that we - * can use to simulate filtering based on width qualifiers on pre-3.2. - * - * @param context Context to load integers from on 3.2+ and to fetch the - * display metrics. - * @param id Id of integer to load. - * @return Associated integer value as reflected by the current display - * metrics. - */ - public static int getResources_getInteger(Context context, int id) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - return context.getResources().getInteger(id); - } - - DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - float widthDp = metrics.widthPixels / metrics.density; - - if (id == R.integer.abs__max_action_buttons) { - if (widthDp >= 600) { - return 5; //values-w600dp - } - if (widthDp >= 500) { - return 4; //values-w500dp - } - if (widthDp >= 360) { - return 3; //values-w360dp - } - return 2; //values - } - - throw new IllegalArgumentException("Unknown integer resource ID " + id); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java deleted file mode 100644 index d022a2465..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.app; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Handler; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentTransaction; -import android.util.TypedValue; -import android.view.ContextThemeWrapper; -import android.view.LayoutInflater; -import android.view.View; -import android.view.Window; -import android.view.accessibility.AccessibilityEvent; -import android.widget.SpinnerAdapter; -import com.actionbarsherlock.R; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; -import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorListenerAdapter; -import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; -import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; -import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; -import com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout; -import com.actionbarsherlock.internal.view.menu.MenuBuilder; -import com.actionbarsherlock.internal.view.menu.MenuPopupHelper; -import com.actionbarsherlock.internal.view.menu.SubMenuBuilder; -import com.actionbarsherlock.internal.widget.ActionBarContainer; -import com.actionbarsherlock.internal.widget.ActionBarContextView; -import com.actionbarsherlock.internal.widget.ActionBarView; -import com.actionbarsherlock.internal.widget.ScrollingTabContainerView; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; -import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; - -/** - * ActionBarImpl is the ActionBar implementation used - * by devices of all screen sizes. If it detects a compatible decor, - * it will split contextual modes across both the ActionBarView at - * the top of the screen and a horizontal LinearLayout at the bottom - * which is normally hidden. - */ -public class ActionBarImpl extends ActionBar { - //UNUSED private static final String TAG = "ActionBarImpl"; - - private Context mContext; - private Context mThemedContext; - private Activity mActivity; - //UNUSED private Dialog mDialog; - - private ActionBarContainer mContainerView; - private ActionBarView mActionView; - private ActionBarContextView mContextView; - private ActionBarContainer mSplitView; - private NineFrameLayout mContentView; - private ScrollingTabContainerView mTabScrollView; - - private ArrayList mTabs = new ArrayList(); - - private TabImpl mSelectedTab; - private int mSavedTabPosition = INVALID_POSITION; - - ActionModeImpl mActionMode; - ActionMode mDeferredDestroyActionMode; - ActionMode.Callback mDeferredModeDestroyCallback; - - private boolean mLastMenuVisibility; - private ArrayList mMenuVisibilityListeners = - new ArrayList(); - - private static final int CONTEXT_DISPLAY_NORMAL = 0; - private static final int CONTEXT_DISPLAY_SPLIT = 1; - - private static final int INVALID_POSITION = -1; - - private int mContextDisplayMode; - private boolean mHasEmbeddedTabs; - - final Handler mHandler = new Handler(); - Runnable mTabSelector; - - private Animator mCurrentShowAnim; - private Animator mCurrentModeAnim; - private boolean mShowHideAnimationEnabled; - boolean mWasHiddenBeforeMode; - - final AnimatorListener mHideListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mContentView != null) { - mContentView.setTranslationY(0); - mContainerView.setTranslationY(0); - } - if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { - mSplitView.setVisibility(View.GONE); - } - mContainerView.setVisibility(View.GONE); - mContainerView.setTransitioning(false); - mCurrentShowAnim = null; - completeDeferredDestroyActionMode(); - } - }; - - final AnimatorListener mShowListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mCurrentShowAnim = null; - mContainerView.requestLayout(); - } - }; - - public ActionBarImpl(Activity activity, int features) { - mActivity = activity; - Window window = activity.getWindow(); - View decor = window.getDecorView(); - init(decor); - - //window.hasFeature() workaround for pre-3.0 - if ((features & (1 << Window.FEATURE_ACTION_BAR_OVERLAY)) == 0) { - mContentView = (NineFrameLayout)decor.findViewById(android.R.id.content); - } - } - - public ActionBarImpl(Dialog dialog) { - //UNUSED mDialog = dialog; - init(dialog.getWindow().getDecorView()); - } - - private void init(View decor) { - mContext = decor.getContext(); - mActionView = (ActionBarView) decor.findViewById(R.id.abs__action_bar); - mContextView = (ActionBarContextView) decor.findViewById( - R.id.abs__action_context_bar); - mContainerView = (ActionBarContainer) decor.findViewById( - R.id.abs__action_bar_container); - mSplitView = (ActionBarContainer) decor.findViewById( - R.id.abs__split_action_bar); - - if (mActionView == null || mContextView == null || mContainerView == null) { - throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + - "with a compatible window decor layout"); - } - - mActionView.setContextView(mContextView); - mContextDisplayMode = mActionView.isSplitActionBar() ? - CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; - - // Older apps get the home button interaction enabled by default. - // Newer apps need to enable it explicitly. - setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion < 14); - - setHasEmbeddedTabs(getResources_getBoolean(mContext, - R.bool.abs__action_bar_embed_tabs)); - } - - public void onConfigurationChanged(Configuration newConfig) { - setHasEmbeddedTabs(getResources_getBoolean(mContext, - R.bool.abs__action_bar_embed_tabs)); - - //Manually dispatch a configuration change to the action bar view on pre-2.2 - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { - mActionView.onConfigurationChanged(newConfig); - if (mContextView != null) { - mContextView.onConfigurationChanged(newConfig); - } - } - } - - private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) { - mHasEmbeddedTabs = hasEmbeddedTabs; - // Switch tab layout configuration if needed - if (!mHasEmbeddedTabs) { - mActionView.setEmbeddedTabView(null); - mContainerView.setTabContainer(mTabScrollView); - } else { - mContainerView.setTabContainer(null); - mActionView.setEmbeddedTabView(mTabScrollView); - } - final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS; - if (mTabScrollView != null) { - mTabScrollView.setVisibility(isInTabMode ? View.VISIBLE : View.GONE); - } - mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode); - } - - private void ensureTabsExist() { - if (mTabScrollView != null) { - return; - } - - ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext); - - if (mHasEmbeddedTabs) { - tabScroller.setVisibility(View.VISIBLE); - mActionView.setEmbeddedTabView(tabScroller); - } else { - tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ? - View.VISIBLE : View.GONE); - mContainerView.setTabContainer(tabScroller); - } - mTabScrollView = tabScroller; - } - - void completeDeferredDestroyActionMode() { - if (mDeferredModeDestroyCallback != null) { - mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode); - mDeferredDestroyActionMode = null; - mDeferredModeDestroyCallback = null; - } - } - - /** - * Enables or disables animation between show/hide states. - * If animation is disabled using this method, animations in progress - * will be finished. - * - * @param enabled true to animate, false to not animate. - */ - public void setShowHideAnimationEnabled(boolean enabled) { - mShowHideAnimationEnabled = enabled; - if (!enabled && mCurrentShowAnim != null) { - mCurrentShowAnim.end(); - } - } - - public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - mMenuVisibilityListeners.add(listener); - } - - public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - mMenuVisibilityListeners.remove(listener); - } - - public void dispatchMenuVisibilityChanged(boolean isVisible) { - if (isVisible == mLastMenuVisibility) { - return; - } - mLastMenuVisibility = isVisible; - - final int count = mMenuVisibilityListeners.size(); - for (int i = 0; i < count; i++) { - mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible); - } - } - - @Override - public void setCustomView(int resId) { - setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false)); - } - - @Override - public void setDisplayUseLogoEnabled(boolean useLogo) { - setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO); - } - - @Override - public void setDisplayShowHomeEnabled(boolean showHome) { - setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME); - } - - @Override - public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { - setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP); - } - - @Override - public void setDisplayShowTitleEnabled(boolean showTitle) { - setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE); - } - - @Override - public void setDisplayShowCustomEnabled(boolean showCustom) { - setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM); - } - - @Override - public void setHomeButtonEnabled(boolean enable) { - mActionView.setHomeButtonEnabled(enable); - } - - @Override - public void setTitle(int resId) { - setTitle(mContext.getString(resId)); - } - - @Override - public void setSubtitle(int resId) { - setSubtitle(mContext.getString(resId)); - } - - public void setSelectedNavigationItem(int position) { - switch (mActionView.getNavigationMode()) { - case NAVIGATION_MODE_TABS: - selectTab(mTabs.get(position)); - break; - case NAVIGATION_MODE_LIST: - mActionView.setDropdownSelectedPosition(position); - break; - default: - throw new IllegalStateException( - "setSelectedNavigationIndex not valid for current navigation mode"); - } - } - - public void removeAllTabs() { - cleanupTabs(); - } - - private void cleanupTabs() { - if (mSelectedTab != null) { - selectTab(null); - } - mTabs.clear(); - if (mTabScrollView != null) { - mTabScrollView.removeAllTabs(); - } - mSavedTabPosition = INVALID_POSITION; - } - - public void setTitle(CharSequence title) { - mActionView.setTitle(title); - } - - public void setSubtitle(CharSequence subtitle) { - mActionView.setSubtitle(subtitle); - } - - public void setDisplayOptions(int options) { - mActionView.setDisplayOptions(options); - } - - public void setDisplayOptions(int options, int mask) { - final int current = mActionView.getDisplayOptions(); - mActionView.setDisplayOptions((options & mask) | (current & ~mask)); - } - - public void setBackgroundDrawable(Drawable d) { - mContainerView.setPrimaryBackground(d); - } - - public void setStackedBackgroundDrawable(Drawable d) { - mContainerView.setStackedBackground(d); - } - - public void setSplitBackgroundDrawable(Drawable d) { - if (mSplitView != null) { - mSplitView.setSplitBackground(d); - } - } - - public View getCustomView() { - return mActionView.getCustomNavigationView(); - } - - public CharSequence getTitle() { - return mActionView.getTitle(); - } - - public CharSequence getSubtitle() { - return mActionView.getSubtitle(); - } - - public int getNavigationMode() { - return mActionView.getNavigationMode(); - } - - public int getDisplayOptions() { - return mActionView.getDisplayOptions(); - } - - public ActionMode startActionMode(ActionMode.Callback callback) { - boolean wasHidden = false; - if (mActionMode != null) { - wasHidden = mWasHiddenBeforeMode; - mActionMode.finish(); - } - - mContextView.killMode(); - ActionModeImpl mode = new ActionModeImpl(callback); - if (mode.dispatchOnCreate()) { - mWasHiddenBeforeMode = !isShowing() || wasHidden; - mode.invalidate(); - mContextView.initForMode(mode); - animateToMode(true); - if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { - // TODO animate this - mSplitView.setVisibility(View.VISIBLE); - } - mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - mActionMode = mode; - return mode; - } - return null; - } - - private void configureTab(Tab tab, int position) { - final TabImpl tabi = (TabImpl) tab; - final ActionBar.TabListener callback = tabi.getCallback(); - - if (callback == null) { - throw new IllegalStateException("Action Bar Tab must have a Callback"); - } - - tabi.setPosition(position); - mTabs.add(position, tabi); - - final int count = mTabs.size(); - for (int i = position + 1; i < count; i++) { - mTabs.get(i).setPosition(i); - } - } - - @Override - public void addTab(Tab tab) { - addTab(tab, mTabs.isEmpty()); - } - - @Override - public void addTab(Tab tab, int position) { - addTab(tab, position, mTabs.isEmpty()); - } - - @Override - public void addTab(Tab tab, boolean setSelected) { - ensureTabsExist(); - mTabScrollView.addTab(tab, setSelected); - configureTab(tab, mTabs.size()); - if (setSelected) { - selectTab(tab); - } - } - - @Override - public void addTab(Tab tab, int position, boolean setSelected) { - ensureTabsExist(); - mTabScrollView.addTab(tab, position, setSelected); - configureTab(tab, position); - if (setSelected) { - selectTab(tab); - } - } - - @Override - public Tab newTab() { - return new TabImpl(); - } - - @Override - public void removeTab(Tab tab) { - removeTabAt(tab.getPosition()); - } - - @Override - public void removeTabAt(int position) { - if (mTabScrollView == null) { - // No tabs around to remove - return; - } - - int selectedTabPosition = mSelectedTab != null - ? mSelectedTab.getPosition() : mSavedTabPosition; - mTabScrollView.removeTabAt(position); - TabImpl removedTab = mTabs.remove(position); - if (removedTab != null) { - removedTab.setPosition(-1); - } - - final int newTabCount = mTabs.size(); - for (int i = position; i < newTabCount; i++) { - mTabs.get(i).setPosition(i); - } - - if (selectedTabPosition == position) { - selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1))); - } - } - - @Override - public void selectTab(Tab tab) { - if (getNavigationMode() != NAVIGATION_MODE_TABS) { - mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION; - return; - } - - FragmentTransaction trans = null; - if (mActivity instanceof FragmentActivity) { - trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() - .disallowAddToBackStack(); - } - - if (mSelectedTab == tab) { - if (mSelectedTab != null) { - mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans); - mTabScrollView.animateToTab(tab.getPosition()); - } - } else { - mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION); - if (mSelectedTab != null) { - mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans); - } - mSelectedTab = (TabImpl) tab; - if (mSelectedTab != null) { - mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans); - } - } - - if (trans != null && !trans.isEmpty()) { - trans.commit(); - } - } - - @Override - public Tab getSelectedTab() { - return mSelectedTab; - } - - @Override - public int getHeight() { - return mContainerView.getHeight(); - } - - @Override - public void show() { - show(true); - } - - void show(boolean markHiddenBeforeMode) { - if (mCurrentShowAnim != null) { - mCurrentShowAnim.end(); - } - if (mContainerView.getVisibility() == View.VISIBLE) { - if (markHiddenBeforeMode) mWasHiddenBeforeMode = false; - return; - } - mContainerView.setVisibility(View.VISIBLE); - - if (mShowHideAnimationEnabled) { - mContainerView.setAlpha(0); - AnimatorSet anim = new AnimatorSet(); - AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 1)); - if (mContentView != null) { - b.with(ObjectAnimator.ofFloat(mContentView, "translationY", - -mContainerView.getHeight(), 0)); - mContainerView.setTranslationY(-mContainerView.getHeight()); - b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0)); - } - if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { - mSplitView.setAlpha(0); - mSplitView.setVisibility(View.VISIBLE); - b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1)); - } - anim.addListener(mShowListener); - mCurrentShowAnim = anim; - anim.start(); - } else { - mContainerView.setAlpha(1); - mContainerView.setTranslationY(0); - mShowListener.onAnimationEnd(null); - } - } - - @Override - public void hide() { - if (mCurrentShowAnim != null) { - mCurrentShowAnim.end(); - } - if (mContainerView.getVisibility() == View.GONE) { - return; - } - - if (mShowHideAnimationEnabled) { - mContainerView.setAlpha(1); - mContainerView.setTransitioning(true); - AnimatorSet anim = new AnimatorSet(); - AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 0)); - if (mContentView != null) { - b.with(ObjectAnimator.ofFloat(mContentView, "translationY", - 0, -mContainerView.getHeight())); - b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", - -mContainerView.getHeight())); - } - if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) { - mSplitView.setAlpha(1); - b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0)); - } - anim.addListener(mHideListener); - mCurrentShowAnim = anim; - anim.start(); - } else { - mHideListener.onAnimationEnd(null); - } - } - - public boolean isShowing() { - return mContainerView.getVisibility() == View.VISIBLE; - } - - void animateToMode(boolean toActionMode) { - if (toActionMode) { - show(false); - } - if (mCurrentModeAnim != null) { - mCurrentModeAnim.end(); - } - - mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); - mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE); - if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) { - mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); - } - } - - public Context getThemedContext() { - if (mThemedContext == null) { - TypedValue outValue = new TypedValue(); - Resources.Theme currentTheme = mContext.getTheme(); - currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme, - outValue, true); - final int targetThemeRes = outValue.resourceId; - - if (targetThemeRes != 0) { //XXX && mContext.getThemeResId() != targetThemeRes) { - mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes); - } else { - mThemedContext = mContext; - } - } - return mThemedContext; - } - - /** - * @hide - */ - public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback { - private ActionMode.Callback mCallback; - private MenuBuilder mMenu; - private WeakReference mCustomView; - - public ActionModeImpl(ActionMode.Callback callback) { - mCallback = callback; - mMenu = new MenuBuilder(getThemedContext()) - .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - mMenu.setCallback(this); - } - - @Override - public MenuInflater getMenuInflater() { - return new MenuInflater(getThemedContext()); - } - - @Override - public Menu getMenu() { - return mMenu; - } - - @Override - public void finish() { - if (mActionMode != this) { - // Not the active action mode - no-op - return; - } - - // If we were hidden before the mode was shown, defer the onDestroy - // callback until the animation is finished and associated relayout - // is about to happen. This lets apps better anticipate visibility - // and layout behavior. - if (mWasHiddenBeforeMode) { - mDeferredDestroyActionMode = this; - mDeferredModeDestroyCallback = mCallback; - } else { - mCallback.onDestroyActionMode(this); - } - mCallback = null; - animateToMode(false); - - // Clear out the context mode views after the animation finishes - mContextView.closeMode(); - mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - - mActionMode = null; - - if (mWasHiddenBeforeMode) { - hide(); - } - } - - @Override - public void invalidate() { - mMenu.stopDispatchingItemsChanged(); - try { - mCallback.onPrepareActionMode(this, mMenu); - } finally { - mMenu.startDispatchingItemsChanged(); - } - } - - public boolean dispatchOnCreate() { - mMenu.stopDispatchingItemsChanged(); - try { - return mCallback.onCreateActionMode(this, mMenu); - } finally { - mMenu.startDispatchingItemsChanged(); - } - } - - @Override - public void setCustomView(View view) { - mContextView.setCustomView(view); - mCustomView = new WeakReference(view); - } - - @Override - public void setSubtitle(CharSequence subtitle) { - mContextView.setSubtitle(subtitle); - } - - @Override - public void setTitle(CharSequence title) { - mContextView.setTitle(title); - } - - @Override - public void setTitle(int resId) { - setTitle(mContext.getResources().getString(resId)); - } - - @Override - public void setSubtitle(int resId) { - setSubtitle(mContext.getResources().getString(resId)); - } - - @Override - public CharSequence getTitle() { - return mContextView.getTitle(); - } - - @Override - public CharSequence getSubtitle() { - return mContextView.getSubtitle(); - } - - @Override - public View getCustomView() { - return mCustomView != null ? mCustomView.get() : null; - } - - public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { - if (mCallback != null) { - return mCallback.onActionItemClicked(this, item); - } else { - return false; - } - } - - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - } - - public boolean onSubMenuSelected(SubMenuBuilder subMenu) { - if (mCallback == null) { - return false; - } - - if (!subMenu.hasVisibleItems()) { - return true; - } - - new MenuPopupHelper(getThemedContext(), subMenu).show(); - return true; - } - - public void onCloseSubMenu(SubMenuBuilder menu) { - } - - public void onMenuModeChange(MenuBuilder menu) { - if (mCallback == null) { - return; - } - invalidate(); - mContextView.showOverflowMenu(); - } - } - - /** - * @hide - */ - public class TabImpl extends ActionBar.Tab { - private ActionBar.TabListener mCallback; - private Object mTag; - private Drawable mIcon; - private CharSequence mText; - private CharSequence mContentDesc; - private int mPosition = -1; - private View mCustomView; - - @Override - public Object getTag() { - return mTag; - } - - @Override - public Tab setTag(Object tag) { - mTag = tag; - return this; - } - - public ActionBar.TabListener getCallback() { - return mCallback; - } - - @Override - public Tab setTabListener(ActionBar.TabListener callback) { - mCallback = callback; - return this; - } - - @Override - public View getCustomView() { - return mCustomView; - } - - @Override - public Tab setCustomView(View view) { - mCustomView = view; - if (mPosition >= 0) { - mTabScrollView.updateTab(mPosition); - } - return this; - } - - @Override - public Tab setCustomView(int layoutResId) { - return setCustomView(LayoutInflater.from(getThemedContext()) - .inflate(layoutResId, null)); - } - - @Override - public Drawable getIcon() { - return mIcon; - } - - @Override - public int getPosition() { - return mPosition; - } - - public void setPosition(int position) { - mPosition = position; - } - - @Override - public CharSequence getText() { - return mText; - } - - @Override - public Tab setIcon(Drawable icon) { - mIcon = icon; - if (mPosition >= 0) { - mTabScrollView.updateTab(mPosition); - } - return this; - } - - @Override - public Tab setIcon(int resId) { - return setIcon(mContext.getResources().getDrawable(resId)); - } - - @Override - public Tab setText(CharSequence text) { - mText = text; - if (mPosition >= 0) { - mTabScrollView.updateTab(mPosition); - } - return this; - } - - @Override - public Tab setText(int resId) { - return setText(mContext.getResources().getText(resId)); - } - - @Override - public void select() { - selectTab(this); - } - - @Override - public Tab setContentDescription(int resId) { - return setContentDescription(mContext.getResources().getText(resId)); - } - - @Override - public Tab setContentDescription(CharSequence contentDesc) { - mContentDesc = contentDesc; - if (mPosition >= 0) { - mTabScrollView.updateTab(mPosition); - } - return this; - } - - @Override - public CharSequence getContentDescription() { - return mContentDesc; - } - } - - @Override - public void setCustomView(View view) { - mActionView.setCustomNavigationView(view); - } - - @Override - public void setCustomView(View view, LayoutParams layoutParams) { - view.setLayoutParams(layoutParams); - mActionView.setCustomNavigationView(view); - } - - @Override - public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { - mActionView.setDropdownAdapter(adapter); - mActionView.setCallback(callback); - } - - @Override - public int getSelectedNavigationIndex() { - switch (mActionView.getNavigationMode()) { - case NAVIGATION_MODE_TABS: - return mSelectedTab != null ? mSelectedTab.getPosition() : -1; - case NAVIGATION_MODE_LIST: - return mActionView.getDropdownSelectedPosition(); - default: - return -1; - } - } - - @Override - public int getNavigationItemCount() { - switch (mActionView.getNavigationMode()) { - case NAVIGATION_MODE_TABS: - return mTabs.size(); - case NAVIGATION_MODE_LIST: - SpinnerAdapter adapter = mActionView.getDropdownAdapter(); - return adapter != null ? adapter.getCount() : 0; - default: - return 0; - } - } - - @Override - public int getTabCount() { - return mTabs.size(); - } - - @Override - public void setNavigationMode(int mode) { - final int oldMode = mActionView.getNavigationMode(); - switch (oldMode) { - case NAVIGATION_MODE_TABS: - mSavedTabPosition = getSelectedNavigationIndex(); - selectTab(null); - mTabScrollView.setVisibility(View.GONE); - break; - } - mActionView.setNavigationMode(mode); - switch (mode) { - case NAVIGATION_MODE_TABS: - ensureTabsExist(); - mTabScrollView.setVisibility(View.VISIBLE); - if (mSavedTabPosition != INVALID_POSITION) { - setSelectedNavigationItem(mSavedTabPosition); - mSavedTabPosition = INVALID_POSITION; - } - break; - } - mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs); - } - - @Override - public Tab getTabAt(int index) { - return mTabs.get(index); - } - - - @Override - public void setIcon(int resId) { - mActionView.setIcon(resId); - } - - @Override - public void setIcon(Drawable icon) { - mActionView.setIcon(icon); - } - - @Override - public void setLogo(int resId) { - mActionView.setLogo(resId); - } - - @Override - public void setLogo(Drawable logo) { - mActionView.setLogo(logo); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java deleted file mode 100644 index 840cb3d27..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java +++ /dev/null @@ -1,468 +0,0 @@ -package com.actionbarsherlock.internal.app; - -import java.util.HashSet; -import java.util.Set; - -import android.app.Activity; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentTransaction; -import android.view.View; -import android.widget.SpinnerAdapter; - -import com.actionbarsherlock.app.ActionBar; - -public class ActionBarWrapper extends ActionBar implements android.app.ActionBar.OnNavigationListener, android.app.ActionBar.OnMenuVisibilityListener { - private final Activity mActivity; - private final android.app.ActionBar mActionBar; - private ActionBar.OnNavigationListener mNavigationListener; - private Set mMenuVisibilityListeners = new HashSet(1); - private FragmentTransaction mFragmentTransaction; - - - public ActionBarWrapper(Activity activity) { - mActivity = activity; - mActionBar = activity.getActionBar(); - if (mActionBar != null) { - mActionBar.addOnMenuVisibilityListener(this); - } - } - - - @Override - public void setHomeButtonEnabled(boolean enabled) { - mActionBar.setHomeButtonEnabled(enabled); - } - - @Override - public Context getThemedContext() { - return mActionBar.getThemedContext(); - } - - @Override - public void setCustomView(View view) { - mActionBar.setCustomView(view); - } - - @Override - public void setCustomView(View view, LayoutParams layoutParams) { - android.app.ActionBar.LayoutParams lp = new android.app.ActionBar.LayoutParams(layoutParams); - lp.gravity = layoutParams.gravity; - lp.bottomMargin = layoutParams.bottomMargin; - lp.topMargin = layoutParams.topMargin; - lp.leftMargin = layoutParams.leftMargin; - lp.rightMargin = layoutParams.rightMargin; - mActionBar.setCustomView(view, lp); - } - - @Override - public void setCustomView(int resId) { - mActionBar.setCustomView(resId); - } - - @Override - public void setIcon(int resId) { - mActionBar.setIcon(resId); - } - - @Override - public void setIcon(Drawable icon) { - mActionBar.setIcon(icon); - } - - @Override - public void setLogo(int resId) { - mActionBar.setLogo(resId); - } - - @Override - public void setLogo(Drawable logo) { - mActionBar.setLogo(logo); - } - - @Override - public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { - mNavigationListener = callback; - mActionBar.setListNavigationCallbacks(adapter, (callback != null) ? this : null); - } - - @Override - public boolean onNavigationItemSelected(int itemPosition, long itemId) { - //This should never be a NullPointerException since we only set - //ourselves as the listener when the callback is not null. - return mNavigationListener.onNavigationItemSelected(itemPosition, itemId); - } - - @Override - public void setSelectedNavigationItem(int position) { - mActionBar.setSelectedNavigationItem(position); - } - - @Override - public int getSelectedNavigationIndex() { - return mActionBar.getSelectedNavigationIndex(); - } - - @Override - public int getNavigationItemCount() { - return mActionBar.getNavigationItemCount(); - } - - @Override - public void setTitle(CharSequence title) { - mActionBar.setTitle(title); - } - - @Override - public void setTitle(int resId) { - mActionBar.setTitle(resId); - } - - @Override - public void setSubtitle(CharSequence subtitle) { - mActionBar.setSubtitle(subtitle); - } - - @Override - public void setSubtitle(int resId) { - mActionBar.setSubtitle(resId); - } - - @Override - public void setDisplayOptions(int options) { - mActionBar.setDisplayOptions(options); - } - - @Override - public void setDisplayOptions(int options, int mask) { - mActionBar.setDisplayOptions(options, mask); - } - - @Override - public void setDisplayUseLogoEnabled(boolean useLogo) { - mActionBar.setDisplayUseLogoEnabled(useLogo); - } - - @Override - public void setDisplayShowHomeEnabled(boolean showHome) { - mActionBar.setDisplayShowHomeEnabled(showHome); - } - - @Override - public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { - mActionBar.setDisplayHomeAsUpEnabled(showHomeAsUp); - } - - @Override - public void setDisplayShowTitleEnabled(boolean showTitle) { - mActionBar.setDisplayShowTitleEnabled(showTitle); - } - - @Override - public void setDisplayShowCustomEnabled(boolean showCustom) { - mActionBar.setDisplayShowCustomEnabled(showCustom); - } - - @Override - public void setBackgroundDrawable(Drawable d) { - mActionBar.setBackgroundDrawable(d); - } - - @Override - public void setStackedBackgroundDrawable(Drawable d) { - mActionBar.setStackedBackgroundDrawable(d); - } - - @Override - public void setSplitBackgroundDrawable(Drawable d) { - mActionBar.setSplitBackgroundDrawable(d); - } - - @Override - public View getCustomView() { - return mActionBar.getCustomView(); - } - - @Override - public CharSequence getTitle() { - return mActionBar.getTitle(); - } - - @Override - public CharSequence getSubtitle() { - return mActionBar.getSubtitle(); - } - - @Override - public int getNavigationMode() { - return mActionBar.getNavigationMode(); - } - - @Override - public void setNavigationMode(int mode) { - mActionBar.setNavigationMode(mode); - } - - @Override - public int getDisplayOptions() { - return mActionBar.getDisplayOptions(); - } - - public class TabWrapper extends ActionBar.Tab implements android.app.ActionBar.TabListener { - final android.app.ActionBar.Tab mNativeTab; - private Object mTag; - private TabListener mListener; - - public TabWrapper(android.app.ActionBar.Tab nativeTab) { - mNativeTab = nativeTab; - mNativeTab.setTag(this); - } - - @Override - public int getPosition() { - return mNativeTab.getPosition(); - } - - @Override - public Drawable getIcon() { - return mNativeTab.getIcon(); - } - - @Override - public CharSequence getText() { - return mNativeTab.getText(); - } - - @Override - public Tab setIcon(Drawable icon) { - mNativeTab.setIcon(icon); - return this; - } - - @Override - public Tab setIcon(int resId) { - mNativeTab.setIcon(resId); - return this; - } - - @Override - public Tab setText(CharSequence text) { - mNativeTab.setText(text); - return this; - } - - @Override - public Tab setText(int resId) { - mNativeTab.setText(resId); - return this; - } - - @Override - public Tab setCustomView(View view) { - mNativeTab.setCustomView(view); - return this; - } - - @Override - public Tab setCustomView(int layoutResId) { - mNativeTab.setCustomView(layoutResId); - return this; - } - - @Override - public View getCustomView() { - return mNativeTab.getCustomView(); - } - - @Override - public Tab setTag(Object obj) { - mTag = obj; - return this; - } - - @Override - public Object getTag() { - return mTag; - } - - @Override - public Tab setTabListener(TabListener listener) { - mNativeTab.setTabListener(listener != null ? this : null); - mListener = listener; - return this; - } - - @Override - public void select() { - mNativeTab.select(); - } - - @Override - public Tab setContentDescription(int resId) { - mNativeTab.setContentDescription(resId); - return this; - } - - @Override - public Tab setContentDescription(CharSequence contentDesc) { - mNativeTab.setContentDescription(contentDesc); - return this; - } - - @Override - public CharSequence getContentDescription() { - return mNativeTab.getContentDescription(); - } - - @Override - public void onTabReselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { - if (mListener != null) { - FragmentTransaction trans = null; - if (mActivity instanceof FragmentActivity) { - trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() - .disallowAddToBackStack(); - } - - mListener.onTabReselected(this, trans); - - if (trans != null && !trans.isEmpty()) { - trans.commit(); - } - } - } - - @Override - public void onTabSelected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { - if (mListener != null) { - - if (mFragmentTransaction == null && mActivity instanceof FragmentActivity) { - mFragmentTransaction = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() - .disallowAddToBackStack(); - } - - mListener.onTabSelected(this, mFragmentTransaction); - - if (mFragmentTransaction != null) { - if (!mFragmentTransaction.isEmpty()) { - mFragmentTransaction.commit(); - } - mFragmentTransaction = null; - } - } - } - - @Override - public void onTabUnselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { - if (mListener != null) { - FragmentTransaction trans = null; - if (mActivity instanceof FragmentActivity) { - trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() - .disallowAddToBackStack(); - mFragmentTransaction = trans; - } - - mListener.onTabUnselected(this, trans); - } - } - } - - @Override - public Tab newTab() { - return new TabWrapper(mActionBar.newTab()); - } - - @Override - public void addTab(Tab tab) { - mActionBar.addTab(((TabWrapper)tab).mNativeTab); - } - - @Override - public void addTab(Tab tab, boolean setSelected) { - mActionBar.addTab(((TabWrapper)tab).mNativeTab, setSelected); - } - - @Override - public void addTab(Tab tab, int position) { - mActionBar.addTab(((TabWrapper)tab).mNativeTab, position); - } - - @Override - public void addTab(Tab tab, int position, boolean setSelected) { - mActionBar.addTab(((TabWrapper)tab).mNativeTab, position, setSelected); - } - - @Override - public void removeTab(Tab tab) { - mActionBar.removeTab(((TabWrapper)tab).mNativeTab); - } - - @Override - public void removeTabAt(int position) { - mActionBar.removeTabAt(position); - } - - @Override - public void removeAllTabs() { - mActionBar.removeAllTabs(); - } - - @Override - public void selectTab(Tab tab) { - mActionBar.selectTab(((TabWrapper)tab).mNativeTab); - } - - @Override - public Tab getSelectedTab() { - android.app.ActionBar.Tab selected = mActionBar.getSelectedTab(); - return (selected != null) ? (Tab)selected.getTag() : null; - } - - @Override - public Tab getTabAt(int index) { - android.app.ActionBar.Tab selected = mActionBar.getTabAt(index); - return (selected != null) ? (Tab)selected.getTag() : null; - } - - @Override - public int getTabCount() { - return mActionBar.getTabCount(); - } - - @Override - public int getHeight() { - return mActionBar.getHeight(); - } - - @Override - public void show() { - mActionBar.show(); - } - - @Override - public void hide() { - mActionBar.hide(); - } - - @Override - public boolean isShowing() { - return mActionBar.isShowing(); - } - - @Override - public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - mMenuVisibilityListeners.add(listener); - } - - @Override - public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - mMenuVisibilityListeners.remove(listener); - } - - @Override - public void onMenuVisibilityChanged(boolean isVisible) { - for (OnMenuVisibilityListener listener : mMenuVisibilityListeners) { - listener.onMenuVisibilityChanged(isVisible); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java deleted file mode 100644 index 2caf5b4a9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import java.util.ArrayList; - -import android.view.animation.Interpolator; - -/** - * This is the superclass for classes which provide basic support for animations which can be - * started, ended, and have AnimatorListeners added to them. - */ -public abstract class Animator implements Cloneable { - - - /** - * The set of listeners to be sent events through the life of an animation. - */ - ArrayList mListeners = null; - - /** - * Starts this animation. If the animation has a nonzero startDelay, the animation will start - * running after that delay elapses. A non-delayed animation will have its initial - * value(s) set immediately, followed by calls to - * {@link AnimatorListener#onAnimationStart(Animator)} for any listeners of this animator. - * - *

The animation started by calling this method will be run on the thread that called - * this method. This thread should have a Looper on it (a runtime exception will be thrown if - * this is not the case). Also, if the animation will animate - * properties of objects in the view hierarchy, then the calling thread should be the UI - * thread for that view hierarchy.

- * - */ - public void start() { - } - - /** - * Cancels the animation. Unlike {@link #end()}, cancel() causes the animation to - * stop in its tracks, sending an - * {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to - * its listeners, followed by an - * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message. - * - *

This method must be called on the thread that is running the animation.

- */ - public void cancel() { - } - - /** - * Ends the animation. This causes the animation to assign the end value of the property being - * animated, then calling the - * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on - * its listeners. - * - *

This method must be called on the thread that is running the animation.

- */ - public void end() { - } - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - * - * @return the number of milliseconds to delay running the animation - */ - public abstract long getStartDelay(); - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - - * @param startDelay The amount of the delay, in milliseconds - */ - public abstract void setStartDelay(long startDelay); - - - /** - * Sets the length of the animation. - * - * @param duration The length of the animation, in milliseconds. - */ - public abstract Animator setDuration(long duration); - - /** - * Gets the length of the animation. - * - * @return The length of the animation, in milliseconds. - */ - public abstract long getDuration(); - - /** - * The time interpolator used in calculating the elapsed fraction of this animation. The - * interpolator determines whether the animation runs with linear or non-linear motion, - * such as acceleration and deceleration. The default value is - * {@link android.view.animation.AccelerateDecelerateInterpolator} - * - * @param value the interpolator to be used by this animation - */ - public abstract void setInterpolator(/*Time*/Interpolator value); - - /** - * Returns whether this Animator is currently running (having been started and gone past any - * initial startDelay period and not yet ended). - * - * @return Whether the Animator is running. - */ - public abstract boolean isRunning(); - - /** - * Returns whether this Animator has been started and not yet ended. This state is a superset - * of the state of {@link #isRunning()}, because an Animator with a nonzero - * {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during the - * delay phase, whereas {@link #isRunning()} will return true only after the delay phase - * is complete. - * - * @return Whether the Animator has been started and not yet ended. - */ - public boolean isStarted() { - // Default method returns value for isRunning(). Subclasses should override to return a - // real value. - return isRunning(); - } - - /** - * Adds a listener to the set of listeners that are sent events through the life of an - * animation, such as start, repeat, and end. - * - * @param listener the listener to be added to the current set of listeners for this animation. - */ - public void addListener(AnimatorListener listener) { - if (mListeners == null) { - mListeners = new ArrayList(); - } - mListeners.add(listener); - } - - /** - * Removes a listener from the set listening to this animation. - * - * @param listener the listener to be removed from the current set of listeners for this - * animation. - */ - public void removeListener(AnimatorListener listener) { - if (mListeners == null) { - return; - } - mListeners.remove(listener); - if (mListeners.size() == 0) { - mListeners = null; - } - } - - /** - * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently - * listening for events on this Animator object. - * - * @return ArrayList The set of listeners. - */ - public ArrayList getListeners() { - return mListeners; - } - - /** - * Removes all listeners from this object. This is equivalent to calling - * getListeners() followed by calling clear() on the - * returned list of listeners. - */ - public void removeAllListeners() { - if (mListeners != null) { - mListeners.clear(); - mListeners = null; - } - } - - @Override - public Animator clone() { - try { - final Animator anim = (Animator) super.clone(); - if (mListeners != null) { - ArrayList oldListeners = mListeners; - anim.mListeners = new ArrayList(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mListeners.add(oldListeners.get(i)); - } - } - return anim; - } catch (CloneNotSupportedException e) { - throw new AssertionError(); - } - } - - /** - * This method tells the object to use appropriate information to extract - * starting values for the animation. For example, a AnimatorSet object will pass - * this call to its child objects to tell them to set up the values. A - * ObjectAnimator object will use the information it has about its target object - * and PropertyValuesHolder objects to get the start values for its properties. - * An ValueAnimator object will ignore the request since it does not have enough - * information (such as a target object) to gather these values. - */ - public void setupStartValues() { - } - - /** - * This method tells the object to use appropriate information to extract - * ending values for the animation. For example, a AnimatorSet object will pass - * this call to its child objects to tell them to set up the values. A - * ObjectAnimator object will use the information it has about its target object - * and PropertyValuesHolder objects to get the start values for its properties. - * An ValueAnimator object will ignore the request since it does not have enough - * information (such as a target object) to gather these values. - */ - public void setupEndValues() { - } - - /** - * Sets the target object whose property will be animated by this animation. Not all subclasses - * operate on target objects (for example, {@link ValueAnimator}, but this method - * is on the superclass for the convenience of dealing generically with those subclasses - * that do handle targets. - * - * @param target The object being animated - */ - public void setTarget(Object target) { - } - - /** - *

An animation listener receives notifications from an animation. - * Notifications indicate animation related events, such as the end or the - * repetition of the animation.

- */ - public static interface AnimatorListener { - /** - *

Notifies the start of the animation.

- * - * @param animation The started animation. - */ - void onAnimationStart(Animator animation); - - /** - *

Notifies the end of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.

- * - * @param animation The animation which reached its end. - */ - void onAnimationEnd(Animator animation); - - /** - *

Notifies the cancellation of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.

- * - * @param animation The animation which was canceled. - */ - void onAnimationCancel(Animator animation); - - /** - *

Notifies the repetition of the animation.

- * - * @param animation The animation which was repeated. - */ - void onAnimationRepeat(Animator animation); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java deleted file mode 100644 index 02ddff48d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -/** - * This adapter class provides empty implementations of the methods from {@link android.animation.Animator.AnimatorListener}. - * Any custom listener that cares only about a subset of the methods of this listener can - * simply subclass this adapter class instead of implementing the interface directly. - */ -public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener { - - /** - * {@inheritDoc} - */ - @Override - public void onAnimationCancel(Animator animation) { - } - - /** - * {@inheritDoc} - */ - @Override - public void onAnimationEnd(Animator animation) { - } - - /** - * {@inheritDoc} - */ - @Override - public void onAnimationRepeat(Animator animation) { - } - - /** - * {@inheritDoc} - */ - @Override - public void onAnimationStart(Animator animation) { - } - -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java deleted file mode 100644 index 3231080c4..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; - -import android.view.animation.Interpolator; - -/** - * This class plays a set of {@link Animator} objects in the specified order. Animations - * can be set up to play together, in sequence, or after a specified delay. - * - *

There are two different approaches to adding animations to a AnimatorSet: - * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or - * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add - * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be - * used in conjunction with methods in the {@link AnimatorSet.Builder Builder} - * class to add animations - * one by one.

- * - *

It is possible to set up a AnimatorSet with circular dependencies between - * its animations. For example, an animation a1 could be set up to start before animation a2, a2 - * before a3, and a3 before a1. The results of this configuration are undefined, but will typically - * result in none of the affected animations being played. Because of this (and because - * circular dependencies do not make logical sense anyway), circular dependencies - * should be avoided, and the dependency flow of animations should only be in one direction. - */ -@SuppressWarnings("unchecked") -public final class AnimatorSet extends Animator { - - /** - * Internal variables - * NOTE: This object implements the clone() method, making a deep copy of any referenced - * objects. As other non-trivial fields are added to this class, make sure to add logic - * to clone() to make deep copies of them. - */ - - /** - * Tracks animations currently being played, so that we know what to - * cancel or end when cancel() or end() is called on this AnimatorSet - */ - private ArrayList mPlayingSet = new ArrayList(); - - /** - * Contains all nodes, mapped to their respective Animators. When new - * dependency information is added for an Animator, we want to add it - * to a single node representing that Animator, not create a new Node - * if one already exists. - */ - private HashMap mNodeMap = new HashMap(); - - /** - * Set of all nodes created for this AnimatorSet. This list is used upon - * starting the set, and the nodes are placed in sorted order into the - * sortedNodes collection. - */ - private ArrayList mNodes = new ArrayList(); - - /** - * The sorted list of nodes. This is the order in which the animations will - * be played. The details about when exactly they will be played depend - * on the dependency relationships of the nodes. - */ - private ArrayList mSortedNodes = new ArrayList(); - - /** - * Flag indicating whether the nodes should be sorted prior to playing. This - * flag allows us to cache the previous sorted nodes so that if the sequence - * is replayed with no changes, it does not have to re-sort the nodes again. - */ - private boolean mNeedsSort = true; - - private AnimatorSetListener mSetListener = null; - - /** - * Flag indicating that the AnimatorSet has been manually - * terminated (by calling cancel() or end()). - * This flag is used to avoid starting other animations when currently-playing - * child animations of this AnimatorSet end. It also determines whether cancel/end - * notifications are sent out via the normal AnimatorSetListener mechanism. - */ - boolean mTerminated = false; - - /** - * Indicates whether an AnimatorSet has been start()'d, whether or - * not there is a nonzero startDelay. - */ - private boolean mStarted = false; - - // The amount of time in ms to delay starting the animation after start() is called - private long mStartDelay = 0; - - // Animator used for a nonzero startDelay - private ValueAnimator mDelayAnim = null; - - - // How long the child animations should last in ms. The default value is negative, which - // simply means that there is no duration set on the AnimatorSet. When a real duration is - // set, it is passed along to the child animations. - private long mDuration = -1; - - - /** - * Sets up this AnimatorSet to play all of the supplied animations at the same time. - * - * @param items The animations that will be started simultaneously. - */ - public void playTogether(Animator... items) { - if (items != null) { - mNeedsSort = true; - Builder builder = play(items[0]); - for (int i = 1; i < items.length; ++i) { - builder.with(items[i]); - } - } - } - - /** - * Sets up this AnimatorSet to play all of the supplied animations at the same time. - * - * @param items The animations that will be started simultaneously. - */ - public void playTogether(Collection items) { - if (items != null && items.size() > 0) { - mNeedsSort = true; - Builder builder = null; - for (Animator anim : items) { - if (builder == null) { - builder = play(anim); - } else { - builder.with(anim); - } - } - } - } - - /** - * Sets up this AnimatorSet to play each of the supplied animations when the - * previous animation ends. - * - * @param items The animations that will be started one after another. - */ - public void playSequentially(Animator... items) { - if (items != null) { - mNeedsSort = true; - if (items.length == 1) { - play(items[0]); - } else { - for (int i = 0; i < items.length - 1; ++i) { - play(items[i]).before(items[i+1]); - } - } - } - } - - /** - * Sets up this AnimatorSet to play each of the supplied animations when the - * previous animation ends. - * - * @param items The animations that will be started one after another. - */ - public void playSequentially(List items) { - if (items != null && items.size() > 0) { - mNeedsSort = true; - if (items.size() == 1) { - play(items.get(0)); - } else { - for (int i = 0; i < items.size() - 1; ++i) { - play(items.get(i)).before(items.get(i+1)); - } - } - } - } - - /** - * Returns the current list of child Animator objects controlled by this - * AnimatorSet. This is a copy of the internal list; modifications to the returned list - * will not affect the AnimatorSet, although changes to the underlying Animator objects - * will affect those objects being managed by the AnimatorSet. - * - * @return ArrayList The list of child animations of this AnimatorSet. - */ - public ArrayList getChildAnimations() { - ArrayList childList = new ArrayList(); - for (Node node : mNodes) { - childList.add(node.animation); - } - return childList; - } - - /** - * Sets the target object for all current {@link #getChildAnimations() child animations} - * of this AnimatorSet that take targets ({@link ObjectAnimator} and - * AnimatorSet). - * - * @param target The object being animated - */ - @Override - public void setTarget(Object target) { - for (Node node : mNodes) { - Animator animation = node.animation; - if (animation instanceof AnimatorSet) { - ((AnimatorSet)animation).setTarget(target); - } else if (animation instanceof ObjectAnimator) { - ((ObjectAnimator)animation).setTarget(target); - } - } - } - - /** - * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations} - * of this AnimatorSet. - * - * @param interpolator the interpolator to be used by each child animation of this AnimatorSet - */ - @Override - public void setInterpolator(/*Time*/Interpolator interpolator) { - for (Node node : mNodes) { - node.animation.setInterpolator(interpolator); - } - } - - /** - * This method creates a Builder object, which is used to - * set up playing constraints. This initial play() method - * tells the Builder the animation that is the dependency for - * the succeeding commands to the Builder. For example, - * calling play(a1).with(a2) sets up the AnimatorSet to play - * a1 and a2 at the same time, - * play(a1).before(a2) sets up the AnimatorSet to play - * a1 first, followed by a2, and - * play(a1).after(a2) sets up the AnimatorSet to play - * a2 first, followed by a1. - * - *

Note that play() is the only way to tell the - * Builder the animation upon which the dependency is created, - * so successive calls to the various functions in Builder - * will all refer to the initial parameter supplied in play() - * as the dependency of the other animations. For example, calling - * play(a1).before(a2).before(a3) will play both a2 - * and a3 when a1 ends; it does not set up a dependency between - * a2 and a3.

- * - * @param anim The animation that is the dependency used in later calls to the - * methods in the returned Builder object. A null parameter will result - * in a null Builder return value. - * @return Builder The object that constructs the AnimatorSet based on the dependencies - * outlined in the calls to play and the other methods in the - * BuilderNote that canceling a AnimatorSet also cancels all of the animations that it - * is responsible for.

- */ - @Override - public void cancel() { - mTerminated = true; - if (isStarted()) { - ArrayList tmpListeners = null; - if (mListeners != null) { - tmpListeners = (ArrayList) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationCancel(this); - } - } - if (mDelayAnim != null && mDelayAnim.isRunning()) { - // If we're currently in the startDelay period, just cancel that animator and - // send out the end event to all listeners - mDelayAnim.cancel(); - } else if (mSortedNodes.size() > 0) { - for (Node node : mSortedNodes) { - node.animation.cancel(); - } - } - if (tmpListeners != null) { - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationEnd(this); - } - } - mStarted = false; - } - } - - /** - * {@inheritDoc} - * - *

Note that ending a AnimatorSet also ends all of the animations that it is - * responsible for.

- */ - @Override - public void end() { - mTerminated = true; - if (isStarted()) { - if (mSortedNodes.size() != mNodes.size()) { - // hasn't been started yet - sort the nodes now, then end them - sortNodes(); - for (Node node : mSortedNodes) { - if (mSetListener == null) { - mSetListener = new AnimatorSetListener(this); - } - node.animation.addListener(mSetListener); - } - } - if (mDelayAnim != null) { - mDelayAnim.cancel(); - } - if (mSortedNodes.size() > 0) { - for (Node node : mSortedNodes) { - node.animation.end(); - } - } - if (mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationEnd(this); - } - } - mStarted = false; - } - } - - /** - * Returns true if any of the child animations of this AnimatorSet have been started and have - * not yet ended. - * @return Whether this AnimatorSet has been started and has not yet ended. - */ - @Override - public boolean isRunning() { - for (Node node : mNodes) { - if (node.animation.isRunning()) { - return true; - } - } - return false; - } - - @Override - public boolean isStarted() { - return mStarted; - } - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - * - * @return the number of milliseconds to delay running the animation - */ - @Override - public long getStartDelay() { - return mStartDelay; - } - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - - * @param startDelay The amount of the delay, in milliseconds - */ - @Override - public void setStartDelay(long startDelay) { - mStartDelay = startDelay; - } - - /** - * Gets the length of each of the child animations of this AnimatorSet. This value may - * be less than 0, which indicates that no duration has been set on this AnimatorSet - * and each of the child animations will use their own duration. - * - * @return The length of the animation, in milliseconds, of each of the child - * animations of this AnimatorSet. - */ - @Override - public long getDuration() { - return mDuration; - } - - /** - * Sets the length of each of the current child animations of this AnimatorSet. By default, - * each child animation will use its own duration. If the duration is set on the AnimatorSet, - * then each child animation inherits this duration. - * - * @param duration The length of the animation, in milliseconds, of each of the child - * animations of this AnimatorSet. - */ - @Override - public AnimatorSet setDuration(long duration) { - if (duration < 0) { - throw new IllegalArgumentException("duration must be a value of zero or greater"); - } - for (Node node : mNodes) { - // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to - // insert "play-after" delays - node.animation.setDuration(duration); - } - mDuration = duration; - return this; - } - - @Override - public void setupStartValues() { - for (Node node : mNodes) { - node.animation.setupStartValues(); - } - } - - @Override - public void setupEndValues() { - for (Node node : mNodes) { - node.animation.setupEndValues(); - } - } - - /** - * {@inheritDoc} - * - *

Starting this AnimatorSet will, in turn, start the animations for which - * it is responsible. The details of when exactly those animations are started depends on - * the dependency relationships that have been set up between the animations. - */ - @Override - public void start() { - mTerminated = false; - mStarted = true; - - // First, sort the nodes (if necessary). This will ensure that sortedNodes - // contains the animation nodes in the correct order. - sortNodes(); - - int numSortedNodes = mSortedNodes.size(); - for (int i = 0; i < numSortedNodes; ++i) { - Node node = mSortedNodes.get(i); - // First, clear out the old listeners - ArrayList oldListeners = node.animation.getListeners(); - if (oldListeners != null && oldListeners.size() > 0) { - final ArrayList clonedListeners = new - ArrayList(oldListeners); - - for (AnimatorListener listener : clonedListeners) { - if (listener instanceof DependencyListener || - listener instanceof AnimatorSetListener) { - node.animation.removeListener(listener); - } - } - } - } - - // nodesToStart holds the list of nodes to be started immediately. We don't want to - // start the animations in the loop directly because we first need to set up - // dependencies on all of the nodes. For example, we don't want to start an animation - // when some other animation also wants to start when the first animation begins. - final ArrayList nodesToStart = new ArrayList(); - for (int i = 0; i < numSortedNodes; ++i) { - Node node = mSortedNodes.get(i); - if (mSetListener == null) { - mSetListener = new AnimatorSetListener(this); - } - if (node.dependencies == null || node.dependencies.size() == 0) { - nodesToStart.add(node); - } else { - int numDependencies = node.dependencies.size(); - for (int j = 0; j < numDependencies; ++j) { - Dependency dependency = node.dependencies.get(j); - dependency.node.animation.addListener( - new DependencyListener(this, node, dependency.rule)); - } - node.tmpDependencies = (ArrayList) node.dependencies.clone(); - } - node.animation.addListener(mSetListener); - } - // Now that all dependencies are set up, start the animations that should be started. - if (mStartDelay <= 0) { - for (Node node : nodesToStart) { - node.animation.start(); - mPlayingSet.add(node.animation); - } - } else { - mDelayAnim = ValueAnimator.ofFloat(0f, 1f); - mDelayAnim.setDuration(mStartDelay); - mDelayAnim.addListener(new AnimatorListenerAdapter() { - boolean canceled = false; - public void onAnimationCancel(Animator anim) { - canceled = true; - } - public void onAnimationEnd(Animator anim) { - if (!canceled) { - int numNodes = nodesToStart.size(); - for (int i = 0; i < numNodes; ++i) { - Node node = nodesToStart.get(i); - node.animation.start(); - mPlayingSet.add(node.animation); - } - } - } - }); - mDelayAnim.start(); - } - if (mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - int numListeners = tmpListeners.size(); - for (int i = 0; i < numListeners; ++i) { - tmpListeners.get(i).onAnimationStart(this); - } - } - if (mNodes.size() == 0 && mStartDelay == 0) { - // Handle unusual case where empty AnimatorSet is started - should send out - // end event immediately since the event will not be sent out at all otherwise - mStarted = false; - if (mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - int numListeners = tmpListeners.size(); - for (int i = 0; i < numListeners; ++i) { - tmpListeners.get(i).onAnimationEnd(this); - } - } - } - } - - @Override - public AnimatorSet clone() { - final AnimatorSet anim = (AnimatorSet) super.clone(); - /* - * The basic clone() operation copies all items. This doesn't work very well for - * AnimatorSet, because it will copy references that need to be recreated and state - * that may not apply. What we need to do now is put the clone in an uninitialized - * state, with fresh, empty data structures. Then we will build up the nodes list - * manually, as we clone each Node (and its animation). The clone will then be sorted, - * and will populate any appropriate lists, when it is started. - */ - anim.mNeedsSort = true; - anim.mTerminated = false; - anim.mStarted = false; - anim.mPlayingSet = new ArrayList(); - anim.mNodeMap = new HashMap(); - anim.mNodes = new ArrayList(); - anim.mSortedNodes = new ArrayList(); - - // Walk through the old nodes list, cloning each node and adding it to the new nodemap. - // One problem is that the old node dependencies point to nodes in the old AnimatorSet. - // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. - HashMap nodeCloneMap = new HashMap(); // - for (Node node : mNodes) { - Node nodeClone = node.clone(); - nodeCloneMap.put(node, nodeClone); - anim.mNodes.add(nodeClone); - anim.mNodeMap.put(nodeClone.animation, nodeClone); - // Clear out the dependencies in the clone; we'll set these up manually later - nodeClone.dependencies = null; - nodeClone.tmpDependencies = null; - nodeClone.nodeDependents = null; - nodeClone.nodeDependencies = null; - // clear out any listeners that were set up by the AnimatorSet; these will - // be set up when the clone's nodes are sorted - ArrayList cloneListeners = nodeClone.animation.getListeners(); - if (cloneListeners != null) { - ArrayList listenersToRemove = null; - for (AnimatorListener listener : cloneListeners) { - if (listener instanceof AnimatorSetListener) { - if (listenersToRemove == null) { - listenersToRemove = new ArrayList(); - } - listenersToRemove.add(listener); - } - } - if (listenersToRemove != null) { - for (AnimatorListener listener : listenersToRemove) { - cloneListeners.remove(listener); - } - } - } - } - // Now that we've cloned all of the nodes, we're ready to walk through their - // dependencies, mapping the old dependencies to the new nodes - for (Node node : mNodes) { - Node nodeClone = nodeCloneMap.get(node); - if (node.dependencies != null) { - for (Dependency dependency : node.dependencies) { - Node clonedDependencyNode = nodeCloneMap.get(dependency.node); - Dependency cloneDependency = new Dependency(clonedDependencyNode, - dependency.rule); - nodeClone.addDependency(cloneDependency); - } - } - } - - return anim; - } - - /** - * This class is the mechanism by which animations are started based on events in other - * animations. If an animation has multiple dependencies on other animations, then - * all dependencies must be satisfied before the animation is started. - */ - private static class DependencyListener implements AnimatorListener { - - private AnimatorSet mAnimatorSet; - - // The node upon which the dependency is based. - private Node mNode; - - // The Dependency rule (WITH or AFTER) that the listener should wait for on - // the node - private int mRule; - - public DependencyListener(AnimatorSet animatorSet, Node node, int rule) { - this.mAnimatorSet = animatorSet; - this.mNode = node; - this.mRule = rule; - } - - /** - * Ignore cancel events for now. We may want to handle this eventually, - * to prevent follow-on animations from running when some dependency - * animation is canceled. - */ - public void onAnimationCancel(Animator animation) { - } - - /** - * An end event is received - see if this is an event we are listening for - */ - public void onAnimationEnd(Animator animation) { - if (mRule == Dependency.AFTER) { - startIfReady(animation); - } - } - - /** - * Ignore repeat events for now - */ - public void onAnimationRepeat(Animator animation) { - } - - /** - * A start event is received - see if this is an event we are listening for - */ - public void onAnimationStart(Animator animation) { - if (mRule == Dependency.WITH) { - startIfReady(animation); - } - } - - /** - * Check whether the event received is one that the node was waiting for. - * If so, mark it as complete and see whether it's time to start - * the animation. - * @param dependencyAnimation the animation that sent the event. - */ - private void startIfReady(Animator dependencyAnimation) { - if (mAnimatorSet.mTerminated) { - // if the parent AnimatorSet was canceled, then don't start any dependent anims - return; - } - Dependency dependencyToRemove = null; - int numDependencies = mNode.tmpDependencies.size(); - for (int i = 0; i < numDependencies; ++i) { - Dependency dependency = mNode.tmpDependencies.get(i); - if (dependency.rule == mRule && - dependency.node.animation == dependencyAnimation) { - // rule fired - remove the dependency and listener and check to - // see whether it's time to start the animation - dependencyToRemove = dependency; - dependencyAnimation.removeListener(this); - break; - } - } - mNode.tmpDependencies.remove(dependencyToRemove); - if (mNode.tmpDependencies.size() == 0) { - // all dependencies satisfied: start the animation - mNode.animation.start(); - mAnimatorSet.mPlayingSet.add(mNode.animation); - } - } - - } - - private class AnimatorSetListener implements AnimatorListener { - - private AnimatorSet mAnimatorSet; - - AnimatorSetListener(AnimatorSet animatorSet) { - mAnimatorSet = animatorSet; - } - - public void onAnimationCancel(Animator animation) { - if (!mTerminated) { - // Listeners are already notified of the AnimatorSet canceling in cancel(). - // The logic below only kicks in when animations end normally - if (mPlayingSet.size() == 0) { - if (mListeners != null) { - int numListeners = mListeners.size(); - for (int i = 0; i < numListeners; ++i) { - mListeners.get(i).onAnimationCancel(mAnimatorSet); - } - } - } - } - } - - public void onAnimationEnd(Animator animation) { - animation.removeListener(this); - mPlayingSet.remove(animation); - Node animNode = mAnimatorSet.mNodeMap.get(animation); - animNode.done = true; - if (!mTerminated) { - // Listeners are already notified of the AnimatorSet ending in cancel() or - // end(); the logic below only kicks in when animations end normally - ArrayList sortedNodes = mAnimatorSet.mSortedNodes; - boolean allDone = true; - int numSortedNodes = sortedNodes.size(); - for (int i = 0; i < numSortedNodes; ++i) { - if (!sortedNodes.get(i).done) { - allDone = false; - break; - } - } - if (allDone) { - // If this was the last child animation to end, then notify listeners that this - // AnimatorSet has ended - if (mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - int numListeners = tmpListeners.size(); - for (int i = 0; i < numListeners; ++i) { - tmpListeners.get(i).onAnimationEnd(mAnimatorSet); - } - } - mAnimatorSet.mStarted = false; - } - } - } - - // Nothing to do - public void onAnimationRepeat(Animator animation) { - } - - // Nothing to do - public void onAnimationStart(Animator animation) { - } - - } - - /** - * This method sorts the current set of nodes, if needed. The sort is a simple - * DependencyGraph sort, which goes like this: - * - All nodes without dependencies become 'roots' - * - while roots list is not null - * - for each root r - * - add r to sorted list - * - remove r as a dependency from any other node - * - any nodes with no dependencies are added to the roots list - */ - private void sortNodes() { - if (mNeedsSort) { - mSortedNodes.clear(); - ArrayList roots = new ArrayList(); - int numNodes = mNodes.size(); - for (int i = 0; i < numNodes; ++i) { - Node node = mNodes.get(i); - if (node.dependencies == null || node.dependencies.size() == 0) { - roots.add(node); - } - } - ArrayList tmpRoots = new ArrayList(); - while (roots.size() > 0) { - int numRoots = roots.size(); - for (int i = 0; i < numRoots; ++i) { - Node root = roots.get(i); - mSortedNodes.add(root); - if (root.nodeDependents != null) { - int numDependents = root.nodeDependents.size(); - for (int j = 0; j < numDependents; ++j) { - Node node = root.nodeDependents.get(j); - node.nodeDependencies.remove(root); - if (node.nodeDependencies.size() == 0) { - tmpRoots.add(node); - } - } - } - } - roots.clear(); - roots.addAll(tmpRoots); - tmpRoots.clear(); - } - mNeedsSort = false; - if (mSortedNodes.size() != mNodes.size()) { - throw new IllegalStateException("Circular dependencies cannot exist" - + " in AnimatorSet"); - } - } else { - // Doesn't need sorting, but still need to add in the nodeDependencies list - // because these get removed as the event listeners fire and the dependencies - // are satisfied - int numNodes = mNodes.size(); - for (int i = 0; i < numNodes; ++i) { - Node node = mNodes.get(i); - if (node.dependencies != null && node.dependencies.size() > 0) { - int numDependencies = node.dependencies.size(); - for (int j = 0; j < numDependencies; ++j) { - Dependency dependency = node.dependencies.get(j); - if (node.nodeDependencies == null) { - node.nodeDependencies = new ArrayList(); - } - if (!node.nodeDependencies.contains(dependency.node)) { - node.nodeDependencies.add(dependency.node); - } - } - } - // nodes are 'done' by default; they become un-done when started, and done - // again when ended - node.done = false; - } - } - } - - /** - * Dependency holds information about the node that some other node is - * dependent upon and the nature of that dependency. - * - */ - private static class Dependency { - static final int WITH = 0; // dependent node must start with this dependency node - static final int AFTER = 1; // dependent node must start when this dependency node finishes - - // The node that the other node with this Dependency is dependent upon - public Node node; - - // The nature of the dependency (WITH or AFTER) - public int rule; - - public Dependency(Node node, int rule) { - this.node = node; - this.rule = rule; - } - } - - /** - * A Node is an embodiment of both the Animator that it wraps as well as - * any dependencies that are associated with that Animation. This includes - * both dependencies upon other nodes (in the dependencies list) as - * well as dependencies of other nodes upon this (in the nodeDependents list). - */ - private static class Node implements Cloneable { - public Animator animation; - - /** - * These are the dependencies that this node's animation has on other - * nodes. For example, if this node's animation should begin with some - * other animation ends, then there will be an item in this node's - * dependencies list for that other animation's node. - */ - public ArrayList dependencies = null; - - /** - * tmpDependencies is a runtime detail. We use the dependencies list for sorting. - * But we also use the list to keep track of when multiple dependencies are satisfied, - * but removing each dependency as it is satisfied. We do not want to remove - * the dependency itself from the list, because we need to retain that information - * if the AnimatorSet is launched in the future. So we create a copy of the dependency - * list when the AnimatorSet starts and use this tmpDependencies list to track the - * list of satisfied dependencies. - */ - public ArrayList tmpDependencies = null; - - /** - * nodeDependencies is just a list of the nodes that this Node is dependent upon. - * This information is used in sortNodes(), to determine when a node is a root. - */ - public ArrayList nodeDependencies = null; - - /** - * nodeDepdendents is the list of nodes that have this node as a dependency. This - * is a utility field used in sortNodes to facilitate removing this node as a - * dependency when it is a root node. - */ - public ArrayList nodeDependents = null; - - /** - * Flag indicating whether the animation in this node is finished. This flag - * is used by AnimatorSet to check, as each animation ends, whether all child animations - * are done and it's time to send out an end event for the entire AnimatorSet. - */ - public boolean done = false; - - /** - * Constructs the Node with the animation that it encapsulates. A Node has no - * dependencies by default; dependencies are added via the addDependency() - * method. - * - * @param animation The animation that the Node encapsulates. - */ - public Node(Animator animation) { - this.animation = animation; - } - - /** - * Add a dependency to this Node. The dependency includes information about the - * node that this node is dependency upon and the nature of the dependency. - * @param dependency - */ - public void addDependency(Dependency dependency) { - if (dependencies == null) { - dependencies = new ArrayList(); - nodeDependencies = new ArrayList(); - } - dependencies.add(dependency); - if (!nodeDependencies.contains(dependency.node)) { - nodeDependencies.add(dependency.node); - } - Node dependencyNode = dependency.node; - if (dependencyNode.nodeDependents == null) { - dependencyNode.nodeDependents = new ArrayList(); - } - dependencyNode.nodeDependents.add(this); - } - - @Override - public Node clone() { - try { - Node node = (Node) super.clone(); - node.animation = animation.clone(); - return node; - } catch (CloneNotSupportedException e) { - throw new AssertionError(); - } - } - } - - /** - * The Builder object is a utility class to facilitate adding animations to a - * AnimatorSet along with the relationships between the various animations. The - * intention of the Builder methods, along with the {@link - * AnimatorSet#play(Animator) play()} method of AnimatorSet is to make it possible - * to express the dependency relationships of animations in a natural way. Developers can also - * use the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link - * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need, - * but it might be easier in some situations to express the AnimatorSet of animations in pairs. - *

- *

The Builder object cannot be constructed directly, but is rather constructed - * internally via a call to {@link AnimatorSet#play(Animator)}.

- *

- *

For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to - * play when anim2 finishes, and anim4 to play when anim3 finishes:

- *
-     *     AnimatorSet s = new AnimatorSet();
-     *     s.play(anim1).with(anim2);
-     *     s.play(anim2).before(anim3);
-     *     s.play(anim4).after(anim3);
-     * 
- *

- *

Note in the example that both {@link Builder#before(Animator)} and {@link - * Builder#after(Animator)} are used. These are just different ways of expressing the same - * relationship and are provided to make it easier to say things in a way that is more natural, - * depending on the situation.

- *

- *

It is possible to make several calls into the same Builder object to express - * multiple relationships. However, note that it is only the animation passed into the initial - * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive - * calls to the Builder object. For example, the following code starts both anim2 - * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and - * anim3: - *

-     *   AnimatorSet s = new AnimatorSet();
-     *   s.play(anim1).before(anim2).before(anim3);
-     * 
- * If the desired result is to play anim1 then anim2 then anim3, this code expresses the - * relationship correctly:

- *
-     *   AnimatorSet s = new AnimatorSet();
-     *   s.play(anim1).before(anim2);
-     *   s.play(anim2).before(anim3);
-     * 
- *

- *

Note that it is possible to express relationships that cannot be resolved and will not - * result in sensible results. For example, play(anim1).after(anim1) makes no - * sense. In general, circular dependencies like this one (or more indirect ones where a depends - * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets - * that can boil down to a simple, one-way relationship of animations starting with, before, and - * after other, different, animations.

- */ - public class Builder { - - /** - * This tracks the current node being processed. It is supplied to the play() method - * of AnimatorSet and passed into the constructor of Builder. - */ - private Node mCurrentNode; - - /** - * package-private constructor. Builders are only constructed by AnimatorSet, when the - * play() method is called. - * - * @param anim The animation that is the dependency for the other animations passed into - * the other methods of this Builder object. - */ - Builder(Animator anim) { - mCurrentNode = mNodeMap.get(anim); - if (mCurrentNode == null) { - mCurrentNode = new Node(anim); - mNodeMap.put(anim, mCurrentNode); - mNodes.add(mCurrentNode); - } - } - - /** - * Sets up the given animation to play at the same time as the animation supplied in the - * {@link AnimatorSet#play(Animator)} call that created this Builder object. - * - * @param anim The animation that will play when the animation supplied to the - * {@link AnimatorSet#play(Animator)} method starts. - */ - public Builder with(Animator anim) { - Node node = mNodeMap.get(anim); - if (node == null) { - node = new Node(anim); - mNodeMap.put(anim, node); - mNodes.add(node); - } - Dependency dependency = new Dependency(mCurrentNode, Dependency.WITH); - node.addDependency(dependency); - return this; - } - - /** - * Sets up the given animation to play when the animation supplied in the - * {@link AnimatorSet#play(Animator)} call that created this Builder object - * ends. - * - * @param anim The animation that will play when the animation supplied to the - * {@link AnimatorSet#play(Animator)} method ends. - */ - public Builder before(Animator anim) { - Node node = mNodeMap.get(anim); - if (node == null) { - node = new Node(anim); - mNodeMap.put(anim, node); - mNodes.add(node); - } - Dependency dependency = new Dependency(mCurrentNode, Dependency.AFTER); - node.addDependency(dependency); - return this; - } - - /** - * Sets up the given animation to play when the animation supplied in the - * {@link AnimatorSet#play(Animator)} call that created this Builder object - * to start when the animation supplied in this method call ends. - * - * @param anim The animation whose end will cause the animation supplied to the - * {@link AnimatorSet#play(Animator)} method to play. - */ - public Builder after(Animator anim) { - Node node = mNodeMap.get(anim); - if (node == null) { - node = new Node(anim); - mNodeMap.put(anim, node); - mNodes.add(node); - } - Dependency dependency = new Dependency(node, Dependency.AFTER); - mCurrentNode.addDependency(dependency); - return this; - } - - /** - * Sets up the animation supplied in the - * {@link AnimatorSet#play(Animator)} call that created this Builder object - * to play when the given amount of time elapses. - * - * @param delay The number of milliseconds that should elapse before the - * animation starts. - */ - public Builder after(long delay) { - // setup dummy ValueAnimator just to run the clock - ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); - anim.setDuration(delay); - after(anim); - return this; - } - - } - -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java deleted file mode 100644 index e41019364..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -/** - * This evaluator can be used to perform type interpolation between float values. - */ -public class FloatEvaluator implements TypeEvaluator { - - /** - * This function returns the result of linearly interpolating the start and end values, with - * fraction representing the proportion between the start and end values. The - * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), - * where x0 is startValue, x1 is endValue, - * and t is fraction. - * - * @param fraction The fraction from the starting to the ending values - * @param startValue The start value; should be of type float or - * Float - * @param endValue The end value; should be of type float or Float - * @return A linear interpolation between the start and end values, given the - * fraction parameter. - */ - public Float evaluate(float fraction, Number startValue, Number endValue) { - float startFloat = startValue.floatValue(); - return startFloat + fraction * (endValue.floatValue() - startFloat); - } -} \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java deleted file mode 100644 index 6d9dafa7a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import java.util.ArrayList; -import android.view.animation.Interpolator; - -import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.FloatKeyframe; - -/** - * This class holds a collection of FloatKeyframe objects and is called by ValueAnimator to calculate - * values between those keyframes for a given animation. The class internal to the animation - * package because it is an implementation detail of how Keyframes are stored and used. - * - *

This type-specific subclass of KeyframeSet, along with the other type-specific subclass for - * int, exists to speed up the getValue() method when there is no custom - * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the - * Object equivalents of these primitive types.

- */ -@SuppressWarnings("unchecked") -class FloatKeyframeSet extends KeyframeSet { - private float firstValue; - private float lastValue; - private float deltaValue; - private boolean firstTime = true; - - public FloatKeyframeSet(FloatKeyframe... keyframes) { - super(keyframes); - } - - @Override - public Object getValue(float fraction) { - return getFloatValue(fraction); - } - - @Override - public FloatKeyframeSet clone() { - ArrayList keyframes = mKeyframes; - int numKeyframes = mKeyframes.size(); - FloatKeyframe[] newKeyframes = new FloatKeyframe[numKeyframes]; - for (int i = 0; i < numKeyframes; ++i) { - newKeyframes[i] = (FloatKeyframe) keyframes.get(i).clone(); - } - FloatKeyframeSet newSet = new FloatKeyframeSet(newKeyframes); - return newSet; - } - - public float getFloatValue(float fraction) { - if (mNumKeyframes == 2) { - if (firstTime) { - firstTime = false; - firstValue = ((FloatKeyframe) mKeyframes.get(0)).getFloatValue(); - lastValue = ((FloatKeyframe) mKeyframes.get(1)).getFloatValue(); - deltaValue = lastValue - firstValue; - } - if (mInterpolator != null) { - fraction = mInterpolator.getInterpolation(fraction); - } - if (mEvaluator == null) { - return firstValue + fraction * deltaValue; - } else { - return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).floatValue(); - } - } - if (fraction <= 0f) { - final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0); - final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(1); - float prevValue = prevKeyframe.getFloatValue(); - float nextValue = nextKeyframe.getFloatValue(); - float prevFraction = prevKeyframe.getFraction(); - float nextFraction = nextKeyframe.getFraction(); - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); - return mEvaluator == null ? - prevValue + intervalFraction * (nextValue - prevValue) : - ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). - floatValue(); - } else if (fraction >= 1f) { - final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 2); - final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 1); - float prevValue = prevKeyframe.getFloatValue(); - float nextValue = nextKeyframe.getFloatValue(); - float prevFraction = prevKeyframe.getFraction(); - float nextFraction = nextKeyframe.getFraction(); - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); - return mEvaluator == null ? - prevValue + intervalFraction * (nextValue - prevValue) : - ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). - floatValue(); - } - FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0); - for (int i = 1; i < mNumKeyframes; ++i) { - FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(i); - if (fraction < nextKeyframe.getFraction()) { - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - float intervalFraction = (fraction - prevKeyframe.getFraction()) / - (nextKeyframe.getFraction() - prevKeyframe.getFraction()); - float prevValue = prevKeyframe.getFloatValue(); - float nextValue = nextKeyframe.getFloatValue(); - return mEvaluator == null ? - prevValue + intervalFraction * (nextValue - prevValue) : - ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). - floatValue(); - } - prevKeyframe = nextKeyframe; - } - // shouldn't get here - return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).floatValue(); - } - -} - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java deleted file mode 100644 index ed5e79ec6..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -/** - * This evaluator can be used to perform type interpolation between int values. - */ -public class IntEvaluator implements TypeEvaluator { - - /** - * This function returns the result of linearly interpolating the start and end values, with - * fraction representing the proportion between the start and end values. The - * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), - * where x0 is startValue, x1 is endValue, - * and t is fraction. - * - * @param fraction The fraction from the starting to the ending values - * @param startValue The start value; should be of type int or - * Integer - * @param endValue The end value; should be of type int or Integer - * @return A linear interpolation between the start and end values, given the - * fraction parameter. - */ - public Integer evaluate(float fraction, Integer startValue, Integer endValue) { - int startInt = startValue; - return (int)(startInt + fraction * (endValue - startInt)); - } -} \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java deleted file mode 100644 index e9215e7f8..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import java.util.ArrayList; -import android.view.animation.Interpolator; - -import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.IntKeyframe; - -/** - * This class holds a collection of IntKeyframe objects and is called by ValueAnimator to calculate - * values between those keyframes for a given animation. The class internal to the animation - * package because it is an implementation detail of how Keyframes are stored and used. - * - *

This type-specific subclass of KeyframeSet, along with the other type-specific subclass for - * float, exists to speed up the getValue() method when there is no custom - * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the - * Object equivalents of these primitive types.

- */ -@SuppressWarnings("unchecked") -class IntKeyframeSet extends KeyframeSet { - private int firstValue; - private int lastValue; - private int deltaValue; - private boolean firstTime = true; - - public IntKeyframeSet(IntKeyframe... keyframes) { - super(keyframes); - } - - @Override - public Object getValue(float fraction) { - return getIntValue(fraction); - } - - @Override - public IntKeyframeSet clone() { - ArrayList keyframes = mKeyframes; - int numKeyframes = mKeyframes.size(); - IntKeyframe[] newKeyframes = new IntKeyframe[numKeyframes]; - for (int i = 0; i < numKeyframes; ++i) { - newKeyframes[i] = (IntKeyframe) keyframes.get(i).clone(); - } - IntKeyframeSet newSet = new IntKeyframeSet(newKeyframes); - return newSet; - } - - public int getIntValue(float fraction) { - if (mNumKeyframes == 2) { - if (firstTime) { - firstTime = false; - firstValue = ((IntKeyframe) mKeyframes.get(0)).getIntValue(); - lastValue = ((IntKeyframe) mKeyframes.get(1)).getIntValue(); - deltaValue = lastValue - firstValue; - } - if (mInterpolator != null) { - fraction = mInterpolator.getInterpolation(fraction); - } - if (mEvaluator == null) { - return firstValue + (int)(fraction * deltaValue); - } else { - return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).intValue(); - } - } - if (fraction <= 0f) { - final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0); - final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(1); - int prevValue = prevKeyframe.getIntValue(); - int nextValue = nextKeyframe.getIntValue(); - float prevFraction = prevKeyframe.getFraction(); - float nextFraction = nextKeyframe.getFraction(); - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); - return mEvaluator == null ? - prevValue + (int)(intervalFraction * (nextValue - prevValue)) : - ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). - intValue(); - } else if (fraction >= 1f) { - final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 2); - final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 1); - int prevValue = prevKeyframe.getIntValue(); - int nextValue = nextKeyframe.getIntValue(); - float prevFraction = prevKeyframe.getFraction(); - float nextFraction = nextKeyframe.getFraction(); - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); - return mEvaluator == null ? - prevValue + (int)(intervalFraction * (nextValue - prevValue)) : - ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).intValue(); - } - IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0); - for (int i = 1; i < mNumKeyframes; ++i) { - IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(i); - if (fraction < nextKeyframe.getFraction()) { - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - float intervalFraction = (fraction - prevKeyframe.getFraction()) / - (nextKeyframe.getFraction() - prevKeyframe.getFraction()); - int prevValue = prevKeyframe.getIntValue(); - int nextValue = nextKeyframe.getIntValue(); - return mEvaluator == null ? - prevValue + (int)(intervalFraction * (nextValue - prevValue)) : - ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). - intValue(); - } - prevKeyframe = nextKeyframe; - } - // shouldn't get here - return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).intValue(); - } - -} - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java deleted file mode 100644 index ab76fa7f6..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import android.view.animation.Interpolator; - -/** - * This class holds a time/value pair for an animation. The Keyframe class is used - * by {@link ValueAnimator} to define the values that the animation target will have over the course - * of the animation. As the time proceeds from one keyframe to the other, the value of the - * target object will animate between the value at the previous keyframe and the value at the - * next keyframe. Each keyframe also holds an optional {@link TimeInterpolator} - * object, which defines the time interpolation over the intervalue preceding the keyframe. - * - *

The Keyframe class itself is abstract. The type-specific factory methods will return - * a subclass of Keyframe specific to the type of value being stored. This is done to improve - * performance when dealing with the most common cases (e.g., float and - * int values). Other types will fall into a more general Keyframe class that - * treats its values as Objects. Unless your animation requires dealing with a custom type - * or a data structure that needs to be animated directly (and evaluated using an implementation - * of {@link TypeEvaluator}), you should stick to using float and int as animations using those - * types have lower runtime overhead than other types.

- */ -@SuppressWarnings("rawtypes") -public abstract class Keyframe implements Cloneable { - /** - * The time at which mValue will hold true. - */ - float mFraction; - - /** - * The type of the value in this Keyframe. This type is determined at construction time, - * based on the type of the value object passed into the constructor. - */ - Class mValueType; - - /** - * The optional time interpolator for the interval preceding this keyframe. A null interpolator - * (the default) results in linear interpolation over the interval. - */ - private /*Time*/Interpolator mInterpolator = null; - - /** - * Flag to indicate whether this keyframe has a valid value. This flag is used when an - * animation first starts, to populate placeholder keyframes with real values derived - * from the target object. - */ - boolean mHasValue = false; - - /** - * Constructs a Keyframe object with the given time and value. The time defines the - * time, as a proportion of an overall animation's duration, at which the value will hold true - * for the animation. The value for the animation between keyframes will be calculated as - * an interpolation between the values at those keyframes. - * - * @param fraction The time, expressed as a value between 0 and 1, representing the fraction - * of time elapsed of the overall animation duration. - * @param value The value that the object will animate to as the animation time approaches - * the time in this keyframe, and the the value animated from as the time passes the time in - * this keyframe. - */ - public static Keyframe ofInt(float fraction, int value) { - return new IntKeyframe(fraction, value); - } - - /** - * Constructs a Keyframe object with the given time. The value at this time will be derived - * from the target object when the animation first starts (note that this implies that keyframes - * with no initial value must be used as part of an {@link ObjectAnimator}). - * The time defines the - * time, as a proportion of an overall animation's duration, at which the value will hold true - * for the animation. The value for the animation between keyframes will be calculated as - * an interpolation between the values at those keyframes. - * - * @param fraction The time, expressed as a value between 0 and 1, representing the fraction - * of time elapsed of the overall animation duration. - */ - public static Keyframe ofInt(float fraction) { - return new IntKeyframe(fraction); - } - - /** - * Constructs a Keyframe object with the given time and value. The time defines the - * time, as a proportion of an overall animation's duration, at which the value will hold true - * for the animation. The value for the animation between keyframes will be calculated as - * an interpolation between the values at those keyframes. - * - * @param fraction The time, expressed as a value between 0 and 1, representing the fraction - * of time elapsed of the overall animation duration. - * @param value The value that the object will animate to as the animation time approaches - * the time in this keyframe, and the the value animated from as the time passes the time in - * this keyframe. - */ - public static Keyframe ofFloat(float fraction, float value) { - return new FloatKeyframe(fraction, value); - } - - /** - * Constructs a Keyframe object with the given time. The value at this time will be derived - * from the target object when the animation first starts (note that this implies that keyframes - * with no initial value must be used as part of an {@link ObjectAnimator}). - * The time defines the - * time, as a proportion of an overall animation's duration, at which the value will hold true - * for the animation. The value for the animation between keyframes will be calculated as - * an interpolation between the values at those keyframes. - * - * @param fraction The time, expressed as a value between 0 and 1, representing the fraction - * of time elapsed of the overall animation duration. - */ - public static Keyframe ofFloat(float fraction) { - return new FloatKeyframe(fraction); - } - - /** - * Constructs a Keyframe object with the given time and value. The time defines the - * time, as a proportion of an overall animation's duration, at which the value will hold true - * for the animation. The value for the animation between keyframes will be calculated as - * an interpolation between the values at those keyframes. - * - * @param fraction The time, expressed as a value between 0 and 1, representing the fraction - * of time elapsed of the overall animation duration. - * @param value The value that the object will animate to as the animation time approaches - * the time in this keyframe, and the the value animated from as the time passes the time in - * this keyframe. - */ - public static Keyframe ofObject(float fraction, Object value) { - return new ObjectKeyframe(fraction, value); - } - - /** - * Constructs a Keyframe object with the given time. The value at this time will be derived - * from the target object when the animation first starts (note that this implies that keyframes - * with no initial value must be used as part of an {@link ObjectAnimator}). - * The time defines the - * time, as a proportion of an overall animation's duration, at which the value will hold true - * for the animation. The value for the animation between keyframes will be calculated as - * an interpolation between the values at those keyframes. - * - * @param fraction The time, expressed as a value between 0 and 1, representing the fraction - * of time elapsed of the overall animation duration. - */ - public static Keyframe ofObject(float fraction) { - return new ObjectKeyframe(fraction, null); - } - - /** - * Indicates whether this keyframe has a valid value. This method is called internally when - * an {@link ObjectAnimator} first starts; keyframes without values are assigned values at - * that time by deriving the value for the property from the target object. - * - * @return boolean Whether this object has a value assigned. - */ - public boolean hasValue() { - return mHasValue; - } - - /** - * Gets the value for this Keyframe. - * - * @return The value for this Keyframe. - */ - public abstract Object getValue(); - - /** - * Sets the value for this Keyframe. - * - * @param value value for this Keyframe. - */ - public abstract void setValue(Object value); - - /** - * Gets the time for this keyframe, as a fraction of the overall animation duration. - * - * @return The time associated with this keyframe, as a fraction of the overall animation - * duration. This should be a value between 0 and 1. - */ - public float getFraction() { - return mFraction; - } - - /** - * Sets the time for this keyframe, as a fraction of the overall animation duration. - * - * @param fraction time associated with this keyframe, as a fraction of the overall animation - * duration. This should be a value between 0 and 1. - */ - public void setFraction(float fraction) { - mFraction = fraction; - } - - /** - * Gets the optional interpolator for this Keyframe. A value of null indicates - * that there is no interpolation, which is the same as linear interpolation. - * - * @return The optional interpolator for this Keyframe. - */ - public /*Time*/Interpolator getInterpolator() { - return mInterpolator; - } - - /** - * Sets the optional interpolator for this Keyframe. A value of null indicates - * that there is no interpolation, which is the same as linear interpolation. - * - * @return The optional interpolator for this Keyframe. - */ - public void setInterpolator(/*Time*/Interpolator interpolator) { - mInterpolator = interpolator; - } - - /** - * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of - * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based - * on the type of Keyframe created. - * - * @return The type of the value stored in the Keyframe. - */ - public Class getType() { - return mValueType; - } - - @Override - public abstract Keyframe clone(); - - /** - * This internal subclass is used for all types which are not int or float. - */ - static class ObjectKeyframe extends Keyframe { - - /** - * The value of the animation at the time mFraction. - */ - Object mValue; - - ObjectKeyframe(float fraction, Object value) { - mFraction = fraction; - mValue = value; - mHasValue = (value != null); - mValueType = mHasValue ? value.getClass() : Object.class; - } - - public Object getValue() { - return mValue; - } - - public void setValue(Object value) { - mValue = value; - mHasValue = (value != null); - } - - @Override - public ObjectKeyframe clone() { - ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mValue); - kfClone.setInterpolator(getInterpolator()); - return kfClone; - } - } - - /** - * Internal subclass used when the keyframe value is of type int. - */ - static class IntKeyframe extends Keyframe { - - /** - * The value of the animation at the time mFraction. - */ - int mValue; - - IntKeyframe(float fraction, int value) { - mFraction = fraction; - mValue = value; - mValueType = int.class; - mHasValue = true; - } - - IntKeyframe(float fraction) { - mFraction = fraction; - mValueType = int.class; - } - - public int getIntValue() { - return mValue; - } - - public Object getValue() { - return mValue; - } - - public void setValue(Object value) { - if (value != null && value.getClass() == Integer.class) { - mValue = ((Integer)value).intValue(); - mHasValue = true; - } - } - - @Override - public IntKeyframe clone() { - IntKeyframe kfClone = new IntKeyframe(getFraction(), mValue); - kfClone.setInterpolator(getInterpolator()); - return kfClone; - } - } - - /** - * Internal subclass used when the keyframe value is of type float. - */ - static class FloatKeyframe extends Keyframe { - /** - * The value of the animation at the time mFraction. - */ - float mValue; - - FloatKeyframe(float fraction, float value) { - mFraction = fraction; - mValue = value; - mValueType = float.class; - mHasValue = true; - } - - FloatKeyframe(float fraction) { - mFraction = fraction; - mValueType = float.class; - } - - public float getFloatValue() { - return mValue; - } - - public Object getValue() { - return mValue; - } - - public void setValue(Object value) { - if (value != null && value.getClass() == Float.class) { - mValue = ((Float)value).floatValue(); - mHasValue = true; - } - } - - @Override - public FloatKeyframe clone() { - FloatKeyframe kfClone = new FloatKeyframe(getFraction(), mValue); - kfClone.setInterpolator(getInterpolator()); - return kfClone; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java deleted file mode 100644 index a71e1ad3c..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import java.util.ArrayList; -import java.util.Arrays; -import android.view.animation.Interpolator; - -import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.FloatKeyframe; -import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.IntKeyframe; -import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.ObjectKeyframe; - -/** - * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate - * values between those keyframes for a given animation. The class internal to the animation - * package because it is an implementation detail of how Keyframes are stored and used. - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -class KeyframeSet { - - int mNumKeyframes; - - Keyframe mFirstKeyframe; - Keyframe mLastKeyframe; - /*Time*/Interpolator mInterpolator; // only used in the 2-keyframe case - ArrayList mKeyframes; // only used when there are not 2 keyframes - TypeEvaluator mEvaluator; - - - public KeyframeSet(Keyframe... keyframes) { - mNumKeyframes = keyframes.length; - mKeyframes = new ArrayList(); - mKeyframes.addAll(Arrays.asList(keyframes)); - mFirstKeyframe = mKeyframes.get(0); - mLastKeyframe = mKeyframes.get(mNumKeyframes - 1); - mInterpolator = mLastKeyframe.getInterpolator(); - } - - public static KeyframeSet ofInt(int... values) { - int numKeyframes = values.length; - IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)]; - if (numKeyframes == 1) { - keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f); - keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]); - } else { - keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]); - } - } - return new IntKeyframeSet(keyframes); - } - - public static KeyframeSet ofFloat(float... values) { - int numKeyframes = values.length; - FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)]; - if (numKeyframes == 1) { - keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f); - keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]); - } else { - keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]); - } - } - return new FloatKeyframeSet(keyframes); - } - - public static KeyframeSet ofKeyframe(Keyframe... keyframes) { - // if all keyframes of same primitive type, create the appropriate KeyframeSet - int numKeyframes = keyframes.length; - boolean hasFloat = false; - boolean hasInt = false; - boolean hasOther = false; - for (int i = 0; i < numKeyframes; ++i) { - if (keyframes[i] instanceof FloatKeyframe) { - hasFloat = true; - } else if (keyframes[i] instanceof IntKeyframe) { - hasInt = true; - } else { - hasOther = true; - } - } - if (hasFloat && !hasInt && !hasOther) { - FloatKeyframe floatKeyframes[] = new FloatKeyframe[numKeyframes]; - for (int i = 0; i < numKeyframes; ++i) { - floatKeyframes[i] = (FloatKeyframe) keyframes[i]; - } - return new FloatKeyframeSet(floatKeyframes); - } else if (hasInt && !hasFloat && !hasOther) { - IntKeyframe intKeyframes[] = new IntKeyframe[numKeyframes]; - for (int i = 0; i < numKeyframes; ++i) { - intKeyframes[i] = (IntKeyframe) keyframes[i]; - } - return new IntKeyframeSet(intKeyframes); - } else { - return new KeyframeSet(keyframes); - } - } - - public static KeyframeSet ofObject(Object... values) { - int numKeyframes = values.length; - ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,2)]; - if (numKeyframes == 1) { - keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f); - keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]); - } else { - keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = (ObjectKeyframe) Keyframe.ofObject((float) i / (numKeyframes - 1), values[i]); - } - } - return new KeyframeSet(keyframes); - } - - /** - * Sets the TypeEvaluator to be used when calculating animated values. This object - * is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet, - * both of which assume their own evaluator to speed up calculations with those primitive - * types. - * - * @param evaluator The TypeEvaluator to be used to calculate animated values. - */ - public void setEvaluator(TypeEvaluator evaluator) { - mEvaluator = evaluator; - } - - @Override - public KeyframeSet clone() { - ArrayList keyframes = mKeyframes; - int numKeyframes = mKeyframes.size(); - Keyframe[] newKeyframes = new Keyframe[numKeyframes]; - for (int i = 0; i < numKeyframes; ++i) { - newKeyframes[i] = keyframes.get(i).clone(); - } - KeyframeSet newSet = new KeyframeSet(newKeyframes); - return newSet; - } - - /** - * Gets the animated value, given the elapsed fraction of the animation (interpolated by the - * animation's interpolator) and the evaluator used to calculate in-between values. This - * function maps the input fraction to the appropriate keyframe interval and a fraction - * between them and returns the interpolated value. Note that the input fraction may fall - * outside the [0-1] bounds, if the animation's interpolator made that happen (e.g., a - * spring interpolation that might send the fraction past 1.0). We handle this situation by - * just using the two keyframes at the appropriate end when the value is outside those bounds. - * - * @param fraction The elapsed fraction of the animation - * @return The animated value. - */ - public Object getValue(float fraction) { - - // Special-case optimization for the common case of only two keyframes - if (mNumKeyframes == 2) { - if (mInterpolator != null) { - fraction = mInterpolator.getInterpolation(fraction); - } - return mEvaluator.evaluate(fraction, mFirstKeyframe.getValue(), - mLastKeyframe.getValue()); - } - if (fraction <= 0f) { - final Keyframe nextKeyframe = mKeyframes.get(1); - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - final float prevFraction = mFirstKeyframe.getFraction(); - float intervalFraction = (fraction - prevFraction) / - (nextKeyframe.getFraction() - prevFraction); - return mEvaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(), - nextKeyframe.getValue()); - } else if (fraction >= 1f) { - final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2); - final /*Time*/Interpolator interpolator = mLastKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - final float prevFraction = prevKeyframe.getFraction(); - float intervalFraction = (fraction - prevFraction) / - (mLastKeyframe.getFraction() - prevFraction); - return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(), - mLastKeyframe.getValue()); - } - Keyframe prevKeyframe = mFirstKeyframe; - for (int i = 1; i < mNumKeyframes; ++i) { - Keyframe nextKeyframe = mKeyframes.get(i); - if (fraction < nextKeyframe.getFraction()) { - final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); - if (interpolator != null) { - fraction = interpolator.getInterpolation(fraction); - } - final float prevFraction = prevKeyframe.getFraction(); - float intervalFraction = (fraction - prevFraction) / - (nextKeyframe.getFraction() - prevFraction); - return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(), - nextKeyframe.getValue()); - } - prevKeyframe = nextKeyframe; - } - // shouldn't reach here - return mLastKeyframe.getValue(); - } - - @Override - public String toString() { - String returnVal = " "; - for (int i = 0; i < mNumKeyframes; ++i) { - returnVal += mKeyframes.get(i).getValue() + " "; - } - return returnVal; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java deleted file mode 100644 index 21d15c02a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import android.util.Log; -//import android.util.Property; - -//import java.lang.reflect.Method; -import java.util.ArrayList; - -/** - * This subclass of {@link ValueAnimator} provides support for animating properties on target objects. - * The constructors of this class take parameters to define the target object that will be animated - * as well as the name of the property that will be animated. Appropriate set/get functions - * are then determined internally and the animation will call these functions as necessary to - * animate the property. - * - * @see #setPropertyName(String) - * - */ -@SuppressWarnings("rawtypes") -public final class ObjectAnimator extends ValueAnimator { - private static final boolean DBG = false; - - // The target object on which the property exists, set in the constructor - private Object mTarget; - - private String mPropertyName; - - //private Property mProperty; - - /** - * Sets the name of the property that will be animated. This name is used to derive - * a setter function that will be called to set animated values. - * For example, a property name of foo will result - * in a call to the function setFoo() on the target object. If either - * valueFrom or valueTo is null, then a getter function will - * also be derived and called. - * - *

For best performance of the mechanism that calls the setter function determined by the - * name of the property being animated, use float or int typed values, - * and make the setter function for those properties have a void return value. This - * will cause the code to take an optimized path for these constrained circumstances. Other - * property types and return types will work, but will have more overhead in processing - * the requests due to normal reflection mechanisms.

- * - *

Note that the setter function derived from this property name - * must take the same parameter type as the - * valueFrom and valueTo properties, otherwise the call to - * the setter function will fail.

- * - *

If this ObjectAnimator has been set up to animate several properties together, - * using more than one PropertyValuesHolder objects, then setting the propertyName simply - * sets the propertyName in the first of those PropertyValuesHolder objects.

- * - * @param propertyName The name of the property being animated. Should not be null. - */ - public void setPropertyName(String propertyName) { - // mValues could be null if this is being constructed piecemeal. Just record the - // propertyName to be used later when setValues() is called if so. - if (mValues != null) { - PropertyValuesHolder valuesHolder = mValues[0]; - String oldName = valuesHolder.getPropertyName(); - valuesHolder.setPropertyName(propertyName); - mValuesMap.remove(oldName); - mValuesMap.put(propertyName, valuesHolder); - } - mPropertyName = propertyName; - // New property/values/target should cause re-initialization prior to starting - mInitialized = false; - } - - /** - * Sets the property that will be animated. Property objects will take precedence over - * properties specified by the {@link #setPropertyName(String)} method. Animations should - * be set up to use one or the other, not both. - * - * @param property The property being animated. Should not be null. - */ - //public void setProperty(Property property) { - // // mValues could be null if this is being constructed piecemeal. Just record the - // // propertyName to be used later when setValues() is called if so. - // if (mValues != null) { - // PropertyValuesHolder valuesHolder = mValues[0]; - // String oldName = valuesHolder.getPropertyName(); - // valuesHolder.setProperty(property); - // mValuesMap.remove(oldName); - // mValuesMap.put(mPropertyName, valuesHolder); - // } - // if (mProperty != null) { - // mPropertyName = property.getName(); - // } - // mProperty = property; - // // New property/values/target should cause re-initialization prior to starting - // mInitialized = false; - //} - - /** - * Gets the name of the property that will be animated. This name will be used to derive - * a setter function that will be called to set animated values. - * For example, a property name of foo will result - * in a call to the function setFoo() on the target object. If either - * valueFrom or valueTo is null, then a getter function will - * also be derived and called. - */ - public String getPropertyName() { - return mPropertyName; - } - - /** - * Creates a new ObjectAnimator object. This default constructor is primarily for - * use internally; the other constructors which take parameters are more generally - * useful. - */ - public ObjectAnimator() { - } - - /** - * Private utility constructor that initializes the target object and name of the - * property being animated. - * - * @param target The object whose property is to be animated. This object should - * have a public method on it called setName(), where name is - * the value of the propertyName parameter. - * @param propertyName The name of the property being animated. - */ - private ObjectAnimator(Object target, String propertyName) { - mTarget = target; - setPropertyName(propertyName); - } - - /** - * Private utility constructor that initializes the target object and property being animated. - * - * @param target The object whose property is to be animated. - * @param property The property being animated. - */ - //private ObjectAnimator(T target, Property property) { - // mTarget = target; - // setProperty(property); - //} - - /** - * Constructs and returns an ObjectAnimator that animates between int values. A single - * value implies that that value is the one being animated to. Two values imply a starting - * and ending values. More than two values imply a starting value, values to animate through - * along the way, and an ending value (these values will be distributed evenly across - * the duration of the animation). - * - * @param target The object whose property is to be animated. This object should - * have a public method on it called setName(), where name is - * the value of the propertyName parameter. - * @param propertyName The name of the property being animated. - * @param values A set of values that the animation will animate between over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - public static ObjectAnimator ofInt(Object target, String propertyName, int... values) { - ObjectAnimator anim = new ObjectAnimator(target, propertyName); - anim.setIntValues(values); - return anim; - } - - /** - * Constructs and returns an ObjectAnimator that animates between int values. A single - * value implies that that value is the one being animated to. Two values imply a starting - * and ending values. More than two values imply a starting value, values to animate through - * along the way, and an ending value (these values will be distributed evenly across - * the duration of the animation). - * - * @param target The object whose property is to be animated. - * @param property The property being animated. - * @param values A set of values that the animation will animate between over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - //public static ObjectAnimator ofInt(T target, Property property, int... values) { - // ObjectAnimator anim = new ObjectAnimator(target, property); - // anim.setIntValues(values); - // return anim; - //} - - /** - * Constructs and returns an ObjectAnimator that animates between float values. A single - * value implies that that value is the one being animated to. Two values imply a starting - * and ending values. More than two values imply a starting value, values to animate through - * along the way, and an ending value (these values will be distributed evenly across - * the duration of the animation). - * - * @param target The object whose property is to be animated. This object should - * have a public method on it called setName(), where name is - * the value of the propertyName parameter. - * @param propertyName The name of the property being animated. - * @param values A set of values that the animation will animate between over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { - ObjectAnimator anim = new ObjectAnimator(target, propertyName); - anim.setFloatValues(values); - return anim; - } - - /** - * Constructs and returns an ObjectAnimator that animates between float values. A single - * value implies that that value is the one being animated to. Two values imply a starting - * and ending values. More than two values imply a starting value, values to animate through - * along the way, and an ending value (these values will be distributed evenly across - * the duration of the animation). - * - * @param target The object whose property is to be animated. - * @param property The property being animated. - * @param values A set of values that the animation will animate between over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - //public static ObjectAnimator ofFloat(T target, Property property, - // float... values) { - // ObjectAnimator anim = new ObjectAnimator(target, property); - // anim.setFloatValues(values); - // return anim; - //} - - /** - * Constructs and returns an ObjectAnimator that animates between Object values. A single - * value implies that that value is the one being animated to. Two values imply a starting - * and ending values. More than two values imply a starting value, values to animate through - * along the way, and an ending value (these values will be distributed evenly across - * the duration of the animation). - * - * @param target The object whose property is to be animated. This object should - * have a public method on it called setName(), where name is - * the value of the propertyName parameter. - * @param propertyName The name of the property being animated. - * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the necessary interpolation between the Object values to derive the animated - * value. - * @param values A set of values that the animation will animate between over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - public static ObjectAnimator ofObject(Object target, String propertyName, - TypeEvaluator evaluator, Object... values) { - ObjectAnimator anim = new ObjectAnimator(target, propertyName); - anim.setObjectValues(values); - anim.setEvaluator(evaluator); - return anim; - } - - /** - * Constructs and returns an ObjectAnimator that animates between Object values. A single - * value implies that that value is the one being animated to. Two values imply a starting - * and ending values. More than two values imply a starting value, values to animate through - * along the way, and an ending value (these values will be distributed evenly across - * the duration of the animation). - * - * @param target The object whose property is to be animated. - * @param property The property being animated. - * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the necessary interpolation between the Object values to derive the animated - * value. - * @param values A set of values that the animation will animate between over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - //public static ObjectAnimator ofObject(T target, Property property, - // TypeEvaluator evaluator, V... values) { - // ObjectAnimator anim = new ObjectAnimator(target, property); - // anim.setObjectValues(values); - // anim.setEvaluator(evaluator); - // return anim; - //} - - /** - * Constructs and returns an ObjectAnimator that animates between the sets of values specified - * in PropertyValueHolder objects. This variant should be used when animating - * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows - * you to associate a set of animation values with a property name. - * - * @param target The object whose property is to be animated. Depending on how the - * PropertyValuesObjects were constructed, the target object should either have the {@link - * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the - * PropertyValuesHOlder objects were created with property names) the target object should have - * public methods on it called setName(), where name is the name of - * the property passed in as the propertyName parameter for each of the - * PropertyValuesHolder objects. - * @param values A set of PropertyValuesHolder objects whose values will be animated between - * over time. - * @return An ObjectAnimator object that is set up to animate between the given values. - */ - public static ObjectAnimator ofPropertyValuesHolder(Object target, - PropertyValuesHolder... values) { - ObjectAnimator anim = new ObjectAnimator(); - anim.mTarget = target; - anim.setValues(values); - return anim; - } - - @Override - public void setIntValues(int... values) { - if (mValues == null || mValues.length == 0) { - // No values yet - this animator is being constructed piecemeal. Init the values with - // whatever the current propertyName is - //if (mProperty != null) { - // setValues(PropertyValuesHolder.ofInt(mProperty, values)); - //} else { - setValues(PropertyValuesHolder.ofInt(mPropertyName, values)); - //} - } else { - super.setIntValues(values); - } - } - - @Override - public void setFloatValues(float... values) { - if (mValues == null || mValues.length == 0) { - // No values yet - this animator is being constructed piecemeal. Init the values with - // whatever the current propertyName is - //if (mProperty != null) { - // setValues(PropertyValuesHolder.ofFloat(mProperty, values)); - //} else { - setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); - //} - } else { - super.setFloatValues(values); - } - } - - @Override - public void setObjectValues(Object... values) { - if (mValues == null || mValues.length == 0) { - // No values yet - this animator is being constructed piecemeal. Init the values with - // whatever the current propertyName is - //if (mProperty != null) { - // setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator)null, values)); - //} else { - setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values)); - //} - } else { - super.setObjectValues(values); - } - } - - @Override - public void start() { - if (DBG) { - Log.d("ObjectAnimator", "Anim target, duration: " + mTarget + ", " + getDuration()); - for (int i = 0; i < mValues.length; ++i) { - PropertyValuesHolder pvh = mValues[i]; - ArrayList keyframes = pvh.mKeyframeSet.mKeyframes; - Log.d("ObjectAnimator", " Values[" + i + "]: " + - pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " + - keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue()); - } - } - super.start(); - } - - /** - * This function is called immediately before processing the first animation - * frame of an animation. If there is a nonzero startDelay, the - * function is called after that delay ends. - * It takes care of the final initialization steps for the - * animation. This includes setting mEvaluator, if the user has not yet - * set it up, and the setter/getter methods, if the user did not supply - * them. - * - *

Overriders of this method should call the superclass method to cause - * internal mechanisms to be set up correctly.

- */ - @Override - void initAnimation() { - if (!mInitialized) { - // mValueType may change due to setter/getter setup; do this before calling super.init(), - // which uses mValueType to set up the default type evaluator. - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupSetterAndGetter(mTarget); - } - super.initAnimation(); - } - } - - /** - * Sets the length of the animation. The default duration is 300 milliseconds. - * - * @param duration The length of the animation, in milliseconds. - * @return ObjectAnimator The object called with setDuration(). This return - * value makes it easier to compose statements together that construct and then set the - * duration, as in - * ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start(). - */ - @Override - public ObjectAnimator setDuration(long duration) { - super.setDuration(duration); - return this; - } - - - /** - * The target object whose property will be animated by this animation - * - * @return The object being animated - */ - public Object getTarget() { - return mTarget; - } - - /** - * Sets the target object whose property will be animated by this animation - * - * @param target The object being animated - */ - @Override - public void setTarget(Object target) { - if (mTarget != target) { - final Object oldTarget = mTarget; - mTarget = target; - if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) { - return; - } - // New target type should cause re-initialization prior to starting - mInitialized = false; - } - } - - @Override - public void setupStartValues() { - initAnimation(); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupStartValue(mTarget); - } - } - - @Override - public void setupEndValues() { - initAnimation(); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setupEndValue(mTarget); - } - } - - /** - * This method is called with the elapsed fraction of the animation during every - * animation frame. This function turns the elapsed fraction into an interpolated fraction - * and then into an animated value (from the evaluator. The function is called mostly during - * animation updates, but it is also called when the end() - * function is called, to set the final value on the property. - * - *

Overrides of this method must call the superclass to perform the calculation - * of the animated value.

- * - * @param fraction The elapsed fraction of the animation. - */ - @Override - void animateValue(float fraction) { - super.animateValue(fraction); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].setAnimatedValue(mTarget); - } - } - - @Override - public ObjectAnimator clone() { - final ObjectAnimator anim = (ObjectAnimator) super.clone(); - return anim; - } - - @Override - public String toString() { - String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " + - mTarget; - if (mValues != null) { - for (int i = 0; i < mValues.length; ++i) { - returnVal += "\n " + mValues[i].toString(); - } - } - return returnVal; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java deleted file mode 100644 index 84f7504ab..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -//import android.util.FloatProperty; -//import android.util.IntProperty; -import android.util.Log; -//import android.util.Property; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * This class holds information about a property and the values that that property - * should take on during an animation. PropertyValuesHolder objects can be used to create - * animations with ValueAnimator or ObjectAnimator that operate on several different properties - * in parallel. - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class PropertyValuesHolder implements Cloneable { - - /** - * The name of the property associated with the values. This need not be a real property, - * unless this object is being used with ObjectAnimator. But this is the name by which - * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator. - */ - String mPropertyName; - - /** - * @hide - */ - //protected Property mProperty; - - /** - * The setter function, if needed. ObjectAnimator hands off this functionality to - * PropertyValuesHolder, since it holds all of the per-property information. This - * property is automatically - * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. - */ - Method mSetter = null; - - /** - * The getter function, if needed. ObjectAnimator hands off this functionality to - * PropertyValuesHolder, since it holds all of the per-property information. This - * property is automatically - * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. - * The getter is only derived and used if one of the values is null. - */ - private Method mGetter = null; - - /** - * The type of values supplied. This information is used both in deriving the setter/getter - * functions and in deriving the type of TypeEvaluator. - */ - Class mValueType; - - /** - * The set of keyframes (time/value pairs) that define this animation. - */ - KeyframeSet mKeyframeSet = null; - - - // type evaluators for the primitive types handled by this implementation - private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); - private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); - - // We try several different types when searching for appropriate setter/getter functions. - // The caller may have supplied values in a type that does not match the setter/getter - // functions (such as the integers 0 and 1 to represent floating point values for alpha). - // Also, the use of generics in constructors means that we end up with the Object versions - // of primitive types (Float vs. float). But most likely, the setter/getter functions - // will take primitive types instead. - // So we supply an ordered array of other types to try before giving up. - private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class, - Double.class, Integer.class}; - private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class, - Float.class, Double.class}; - private static Class[] DOUBLE_VARIANTS = {double.class, Double.class, float.class, int.class, - Float.class, Integer.class}; - - // These maps hold all property entries for a particular class. This map - // is used to speed up property/setter/getter lookups for a given class/property - // combination. No need to use reflection on the combination more than once. - private static final HashMap> sSetterPropertyMap = - new HashMap>(); - private static final HashMap> sGetterPropertyMap = - new HashMap>(); - - // This lock is used to ensure that only one thread is accessing the property maps - // at a time. - final ReentrantReadWriteLock mPropertyMapLock = new ReentrantReadWriteLock(); - - // Used to pass single value to varargs parameter in setter invocation - final Object[] mTmpValueArray = new Object[1]; - - /** - * The type evaluator used to calculate the animated values. This evaluator is determined - * automatically based on the type of the start/end objects passed into the constructor, - * but the system only knows about the primitive types int and float. Any other - * type will need to set the evaluator to a custom evaluator for that type. - */ - private TypeEvaluator mEvaluator; - - /** - * The value most recently calculated by calculateValue(). This is set during - * that function and might be retrieved later either by ValueAnimator.animatedValue() or - * by the property-setting logic in ObjectAnimator.animatedValue(). - */ - private Object mAnimatedValue; - - /** - * Internal utility constructor, used by the factory methods to set the property name. - * @param propertyName The name of the property for this holder. - */ - private PropertyValuesHolder(String propertyName) { - mPropertyName = propertyName; - } - - /** - * Internal utility constructor, used by the factory methods to set the property. - * @param property The property for this holder. - */ - //private PropertyValuesHolder(Property property) { - // mProperty = property; - // if (property != null) { - // mPropertyName = property.getName(); - // } - //} - - /** - * Constructs and returns a PropertyValuesHolder with a given property name and - * set of int values. - * @param propertyName The name of the property being animated. - * @param values The values that the named property will animate between. - * @return PropertyValuesHolder The constructed PropertyValuesHolder object. - */ - public static PropertyValuesHolder ofInt(String propertyName, int... values) { - return new IntPropertyValuesHolder(propertyName, values); - } - - /** - * Constructs and returns a PropertyValuesHolder with a given property and - * set of int values. - * @param property The property being animated. Should not be null. - * @param values The values that the property will animate between. - * @return PropertyValuesHolder The constructed PropertyValuesHolder object. - */ - //public static PropertyValuesHolder ofInt(Property property, int... values) { - // return new IntPropertyValuesHolder(property, values); - //} - - /** - * Constructs and returns a PropertyValuesHolder with a given property name and - * set of float values. - * @param propertyName The name of the property being animated. - * @param values The values that the named property will animate between. - * @return PropertyValuesHolder The constructed PropertyValuesHolder object. - */ - public static PropertyValuesHolder ofFloat(String propertyName, float... values) { - return new FloatPropertyValuesHolder(propertyName, values); - } - - /** - * Constructs and returns a PropertyValuesHolder with a given property and - * set of float values. - * @param property The property being animated. Should not be null. - * @param values The values that the property will animate between. - * @return PropertyValuesHolder The constructed PropertyValuesHolder object. - */ - //public static PropertyValuesHolder ofFloat(Property property, float... values) { - // return new FloatPropertyValuesHolder(property, values); - //} - - /** - * Constructs and returns a PropertyValuesHolder with a given property name and - * set of Object values. This variant also takes a TypeEvaluator because the system - * cannot automatically interpolate between objects of unknown type. - * - * @param propertyName The name of the property being animated. - * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the necessary interpolation between the Object values to derive the animated - * value. - * @param values The values that the named property will animate between. - * @return PropertyValuesHolder The constructed PropertyValuesHolder object. - */ - public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, - Object... values) { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.setObjectValues(values); - pvh.setEvaluator(evaluator); - return pvh; - } - - /** - * Constructs and returns a PropertyValuesHolder with a given property and - * set of Object values. This variant also takes a TypeEvaluator because the system - * cannot automatically interpolate between objects of unknown type. - * - * @param property The property being animated. Should not be null. - * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the necessary interpolation between the Object values to derive the animated - * value. - * @param values The values that the property will animate between. - * @return PropertyValuesHolder The constructed PropertyValuesHolder object. - */ - //public static PropertyValuesHolder ofObject(Property property, - // TypeEvaluator evaluator, V... values) { - // PropertyValuesHolder pvh = new PropertyValuesHolder(property); - // pvh.setObjectValues(values); - // pvh.setEvaluator(evaluator); - // return pvh; - //} - - /** - * Constructs and returns a PropertyValuesHolder object with the specified property name and set - * of values. These values can be of any type, but the type should be consistent so that - * an appropriate {@link android.animation.TypeEvaluator} can be found that matches - * the common type. - *

If there is only one value, it is assumed to be the end value of an animation, - * and an initial value will be derived, if possible, by calling a getter function - * on the object. Also, if any value is null, the value will be filled in when the animation - * starts in the same way. This mechanism of automatically getting null values only works - * if the PropertyValuesHolder object is used in conjunction - * {@link ObjectAnimator}, and with a getter function - * derived automatically from propertyName, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * @param propertyName The name of the property associated with this set of values. This - * can be the actual property name to be used when using a ObjectAnimator object, or - * just a name used to get animated values, such as if this object is used with an - * ValueAnimator object. - * @param values The set of values to animate between. - */ - public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) { - KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); - if (keyframeSet instanceof IntKeyframeSet) { - return new IntPropertyValuesHolder(propertyName, (IntKeyframeSet) keyframeSet); - } else if (keyframeSet instanceof FloatKeyframeSet) { - return new FloatPropertyValuesHolder(propertyName, (FloatKeyframeSet) keyframeSet); - } - else { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.mKeyframeSet = keyframeSet; - pvh.mValueType = values[0].getType(); - return pvh; - } - } - - /** - * Constructs and returns a PropertyValuesHolder object with the specified property and set - * of values. These values can be of any type, but the type should be consistent so that - * an appropriate {@link android.animation.TypeEvaluator} can be found that matches - * the common type. - *

If there is only one value, it is assumed to be the end value of an animation, - * and an initial value will be derived, if possible, by calling the property's - * {@link android.util.Property#get(Object)} function. - * Also, if any value is null, the value will be filled in when the animation - * starts in the same way. This mechanism of automatically getting null values only works - * if the PropertyValuesHolder object is used in conjunction with - * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * @param property The property associated with this set of values. Should not be null. - * @param values The set of values to animate between. - */ - //public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) { - // KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); - // if (keyframeSet instanceof IntKeyframeSet) { - // return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet); - // } else if (keyframeSet instanceof FloatKeyframeSet) { - // return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet); - // } - // else { - // PropertyValuesHolder pvh = new PropertyValuesHolder(property); - // pvh.mKeyframeSet = keyframeSet; - // pvh.mValueType = ((Keyframe)values[0]).getType(); - // return pvh; - // } - //} - - /** - * Set the animated values for this object to this set of ints. - * If there is only one value, it is assumed to be the end value of an animation, - * and an initial value will be derived, if possible, by calling a getter function - * on the object. Also, if any value is null, the value will be filled in when the animation - * starts in the same way. This mechanism of automatically getting null values only works - * if the PropertyValuesHolder object is used in conjunction - * {@link ObjectAnimator}, and with a getter function - * derived automatically from propertyName, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * - * @param values One or more values that the animation will animate between. - */ - public void setIntValues(int... values) { - mValueType = int.class; - mKeyframeSet = KeyframeSet.ofInt(values); - } - - /** - * Set the animated values for this object to this set of floats. - * If there is only one value, it is assumed to be the end value of an animation, - * and an initial value will be derived, if possible, by calling a getter function - * on the object. Also, if any value is null, the value will be filled in when the animation - * starts in the same way. This mechanism of automatically getting null values only works - * if the PropertyValuesHolder object is used in conjunction - * {@link ObjectAnimator}, and with a getter function - * derived automatically from propertyName, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * - * @param values One or more values that the animation will animate between. - */ - public void setFloatValues(float... values) { - mValueType = float.class; - mKeyframeSet = KeyframeSet.ofFloat(values); - } - - /** - * Set the animated values for this object to this set of Keyframes. - * - * @param values One or more values that the animation will animate between. - */ - public void setKeyframes(Keyframe... values) { - int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; - mValueType = values[0].getType(); - for (int i = 0; i < numKeyframes; ++i) { - keyframes[i] = values[i]; - } - mKeyframeSet = new KeyframeSet(keyframes); - } - - /** - * Set the animated values for this object to this set of Objects. - * If there is only one value, it is assumed to be the end value of an animation, - * and an initial value will be derived, if possible, by calling a getter function - * on the object. Also, if any value is null, the value will be filled in when the animation - * starts in the same way. This mechanism of automatically getting null values only works - * if the PropertyValuesHolder object is used in conjunction - * {@link ObjectAnimator}, and with a getter function - * derived automatically from propertyName, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * - * @param values One or more values that the animation will animate between. - */ - public void setObjectValues(Object... values) { - mValueType = values[0].getClass(); - mKeyframeSet = KeyframeSet.ofObject(values); - } - - /** - * Determine the setter or getter function using the JavaBeans convention of setFoo or - * getFoo for a property named 'foo'. This function figures out what the name of the - * function should be and uses reflection to find the Method with that name on the - * target object. - * - * @param targetClass The class to search for the method - * @param prefix "set" or "get", depending on whether we need a setter or getter. - * @param valueType The type of the parameter (in the case of a setter). This type - * is derived from the values set on this PropertyValuesHolder. This type is used as - * a first guess at the parameter type, but we check for methods with several different - * types to avoid problems with slight mis-matches between supplied values and actual - * value types used on the setter. - * @return Method the method associated with mPropertyName. - */ - private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) { - // TODO: faster implementation... - Method returnVal = null; - String methodName = getMethodName(prefix, mPropertyName); - Class args[] = null; - if (valueType == null) { - try { - returnVal = targetClass.getMethod(methodName, args); - } catch (NoSuchMethodException e) { - Log.e("PropertyValuesHolder", targetClass.getSimpleName() + " - " + - "Couldn't find no-arg method for property " + mPropertyName + ": " + e); - } - } else { - args = new Class[1]; - Class typeVariants[]; - if (mValueType.equals(Float.class)) { - typeVariants = FLOAT_VARIANTS; - } else if (mValueType.equals(Integer.class)) { - typeVariants = INTEGER_VARIANTS; - } else if (mValueType.equals(Double.class)) { - typeVariants = DOUBLE_VARIANTS; - } else { - typeVariants = new Class[1]; - typeVariants[0] = mValueType; - } - for (Class typeVariant : typeVariants) { - args[0] = typeVariant; - try { - returnVal = targetClass.getMethod(methodName, args); - // change the value type to suit - mValueType = typeVariant; - return returnVal; - } catch (NoSuchMethodException e) { - // Swallow the error and keep trying other variants - } - } - // If we got here, then no appropriate function was found - Log.e("PropertyValuesHolder", - "Couldn't find " + prefix + "ter property " + mPropertyName + - " for " + targetClass.getSimpleName() + - " with value type "+ mValueType); - } - - return returnVal; - } - - - /** - * Returns the setter or getter requested. This utility function checks whether the - * requested method exists in the propertyMapMap cache. If not, it calls another - * utility function to request the Method from the targetClass directly. - * @param targetClass The Class on which the requested method should exist. - * @param propertyMapMap The cache of setters/getters derived so far. - * @param prefix "set" or "get", for the setter or getter. - * @param valueType The type of parameter passed into the method (null for getter). - * @return Method the method associated with mPropertyName. - */ - private Method setupSetterOrGetter(Class targetClass, - HashMap> propertyMapMap, - String prefix, Class valueType) { - Method setterOrGetter = null; - try { - // Have to lock property map prior to reading it, to guard against - // another thread putting something in there after we've checked it - // but before we've added an entry to it - mPropertyMapLock.writeLock().lock(); - HashMap propertyMap = propertyMapMap.get(targetClass); - if (propertyMap != null) { - setterOrGetter = propertyMap.get(mPropertyName); - } - if (setterOrGetter == null) { - setterOrGetter = getPropertyFunction(targetClass, prefix, valueType); - if (propertyMap == null) { - propertyMap = new HashMap(); - propertyMapMap.put(targetClass, propertyMap); - } - propertyMap.put(mPropertyName, setterOrGetter); - } - } finally { - mPropertyMapLock.writeLock().unlock(); - } - return setterOrGetter; - } - - /** - * Utility function to get the setter from targetClass - * @param targetClass The Class on which the requested method should exist. - */ - void setupSetter(Class targetClass) { - mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", mValueType); - } - - /** - * Utility function to get the getter from targetClass - */ - private void setupGetter(Class targetClass) { - mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null); - } - - /** - * Internal function (called from ObjectAnimator) to set up the setter and getter - * prior to running the animation. If the setter has not been manually set for this - * object, it will be derived automatically given the property name, target object, and - * types of values supplied. If no getter has been set, it will be supplied iff any of the - * supplied values was null. If there is a null value, then the getter (supplied or derived) - * will be called to set those null values to the current value of the property - * on the target object. - * @param target The object on which the setter (and possibly getter) exist. - */ - void setupSetterAndGetter(Object target) { - //if (mProperty != null) { - // // check to make sure that mProperty is on the class of target - // try { - // Object testValue = mProperty.get(target); - // for (Keyframe kf : mKeyframeSet.mKeyframes) { - // if (!kf.hasValue()) { - // kf.setValue(mProperty.get(target)); - // } - // } - // return; - // } catch (ClassCastException e) { - // Log.e("PropertyValuesHolder","No such property (" + mProperty.getName() + - // ") on target object " + target + ". Trying reflection instead"); - // mProperty = null; - // } - //} - Class targetClass = target.getClass(); - if (mSetter == null) { - setupSetter(targetClass); - } - for (Keyframe kf : mKeyframeSet.mKeyframes) { - if (!kf.hasValue()) { - if (mGetter == null) { - setupGetter(targetClass); - } - try { - kf.setValue(mGetter.invoke(target)); - } catch (InvocationTargetException e) { - Log.e("PropertyValuesHolder", e.toString()); - } catch (IllegalAccessException e) { - Log.e("PropertyValuesHolder", e.toString()); - } - } - } - } - - /** - * Utility function to set the value stored in a particular Keyframe. The value used is - * whatever the value is for the property name specified in the keyframe on the target object. - * - * @param target The target object from which the current value should be extracted. - * @param kf The keyframe which holds the property name and value. - */ - private void setupValue(Object target, Keyframe kf) { - //if (mProperty != null) { - // kf.setValue(mProperty.get(target)); - //} - try { - if (mGetter == null) { - Class targetClass = target.getClass(); - setupGetter(targetClass); - } - kf.setValue(mGetter.invoke(target)); - } catch (InvocationTargetException e) { - Log.e("PropertyValuesHolder", e.toString()); - } catch (IllegalAccessException e) { - Log.e("PropertyValuesHolder", e.toString()); - } - } - - /** - * This function is called by ObjectAnimator when setting the start values for an animation. - * The start values are set according to the current values in the target object. The - * property whose value is extracted is whatever is specified by the propertyName of this - * PropertyValuesHolder object. - * - * @param target The object which holds the start values that should be set. - */ - void setupStartValue(Object target) { - setupValue(target, mKeyframeSet.mKeyframes.get(0)); - } - - /** - * This function is called by ObjectAnimator when setting the end values for an animation. - * The end values are set according to the current values in the target object. The - * property whose value is extracted is whatever is specified by the propertyName of this - * PropertyValuesHolder object. - * - * @param target The object which holds the start values that should be set. - */ - void setupEndValue(Object target) { - setupValue(target, mKeyframeSet.mKeyframes.get(mKeyframeSet.mKeyframes.size() - 1)); - } - - @Override - public PropertyValuesHolder clone() { - try { - PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); - newPVH.mPropertyName = mPropertyName; - //newPVH.mProperty = mProperty; - newPVH.mKeyframeSet = mKeyframeSet.clone(); - newPVH.mEvaluator = mEvaluator; - return newPVH; - } catch (CloneNotSupportedException e) { - // won't reach here - return null; - } - } - - /** - * Internal function to set the value on the target object, using the setter set up - * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator - * to handle turning the value calculated by ValueAnimator into a value set on the object - * according to the name of the property. - * @param target The target object on which the value is set - */ - void setAnimatedValue(Object target) { - //if (mProperty != null) { - // mProperty.set(target, getAnimatedValue()); - //} - if (mSetter != null) { - try { - mTmpValueArray[0] = getAnimatedValue(); - mSetter.invoke(target, mTmpValueArray); - } catch (InvocationTargetException e) { - Log.e("PropertyValuesHolder", e.toString()); - } catch (IllegalAccessException e) { - Log.e("PropertyValuesHolder", e.toString()); - } - } - } - - /** - * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used - * to calculate animated values. - */ - void init() { - if (mEvaluator == null) { - // We already handle int and float automatically, but not their Object - // equivalents - mEvaluator = (mValueType == Integer.class) ? sIntEvaluator : - (mValueType == Float.class) ? sFloatEvaluator : - null; - } - if (mEvaluator != null) { - // KeyframeSet knows how to evaluate the common types - only give it a custom - // evaluator if one has been set on this class - mKeyframeSet.setEvaluator(mEvaluator); - } - } - - /** - * The TypeEvaluator will the automatically determined based on the type of values - * supplied to PropertyValuesHolder. The evaluator can be manually set, however, if so - * desired. This may be important in cases where either the type of the values supplied - * do not match the way that they should be interpolated between, or if the values - * are of a custom type or one not currently understood by the animation system. Currently, - * only values of type float and int (and their Object equivalents: Float - * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator. - * @param evaluator - */ - public void setEvaluator(TypeEvaluator evaluator) { - mEvaluator = evaluator; - mKeyframeSet.setEvaluator(evaluator); - } - - /** - * Function used to calculate the value according to the evaluator set up for - * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue(). - * - * @param fraction The elapsed, interpolated fraction of the animation. - */ - void calculateValue(float fraction) { - mAnimatedValue = mKeyframeSet.getValue(fraction); - } - - /** - * Sets the name of the property that will be animated. This name is used to derive - * a setter function that will be called to set animated values. - * For example, a property name of foo will result - * in a call to the function setFoo() on the target object. If either - * valueFrom or valueTo is null, then a getter function will - * also be derived and called. - * - *

Note that the setter function derived from this property name - * must take the same parameter type as the - * valueFrom and valueTo properties, otherwise the call to - * the setter function will fail.

- * - * @param propertyName The name of the property being animated. - */ - public void setPropertyName(String propertyName) { - mPropertyName = propertyName; - } - - /** - * Sets the property that will be animated. - * - *

Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property - * must exist on the target object specified in that ObjectAnimator.

- * - * @param property The property being animated. - */ - //public void setProperty(Property property) { - // mProperty = property; - //} - - /** - * Gets the name of the property that will be animated. This name will be used to derive - * a setter function that will be called to set animated values. - * For example, a property name of foo will result - * in a call to the function setFoo() on the target object. If either - * valueFrom or valueTo is null, then a getter function will - * also be derived and called. - */ - public String getPropertyName() { - return mPropertyName; - } - - /** - * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value - * most recently calculated in calculateValue(). - * @return - */ - Object getAnimatedValue() { - return mAnimatedValue; - } - - @Override - public String toString() { - return mPropertyName + ": " + mKeyframeSet.toString(); - } - - /** - * Utility method to derive a setter/getter method name from a property name, where the - * prefix is typically "set" or "get" and the first letter of the property name is - * capitalized. - * - * @param prefix The precursor to the method name, before the property name begins, typically - * "set" or "get". - * @param propertyName The name of the property that represents the bulk of the method name - * after the prefix. The first letter of this word will be capitalized in the resulting - * method name. - * @return String the property name converted to a method name according to the conventions - * specified above. - */ - static String getMethodName(String prefix, String propertyName) { - if (propertyName == null || propertyName.length() == 0) { - // shouldn't get here - return prefix; - } - char firstLetter = Character.toUpperCase(propertyName.charAt(0)); - String theRest = propertyName.substring(1); - return prefix + firstLetter + theRest; - } - - static class IntPropertyValuesHolder extends PropertyValuesHolder { - - // Cache JNI functions to avoid looking them up twice - //private static final HashMap> sJNISetterPropertyMap = - // new HashMap>(); - //int mJniSetter; - //private IntProperty mIntProperty; - - IntKeyframeSet mIntKeyframeSet; - int mIntAnimatedValue; - - public IntPropertyValuesHolder(String propertyName, IntKeyframeSet keyframeSet) { - super(propertyName); - mValueType = int.class; - mKeyframeSet = keyframeSet; - mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; - } - - //public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) { - // super(property); - // mValueType = int.class; - // mKeyframeSet = keyframeSet; - // mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; - // if (property instanceof IntProperty) { - // mIntProperty = (IntProperty) mProperty; - // } - //} - - public IntPropertyValuesHolder(String propertyName, int... values) { - super(propertyName); - setIntValues(values); - } - - //public IntPropertyValuesHolder(Property property, int... values) { - // super(property); - // setIntValues(values); - // if (property instanceof IntProperty) { - // mIntProperty = (IntProperty) mProperty; - // } - //} - - @Override - public void setIntValues(int... values) { - super.setIntValues(values); - mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; - } - - @Override - void calculateValue(float fraction) { - mIntAnimatedValue = mIntKeyframeSet.getIntValue(fraction); - } - - @Override - Object getAnimatedValue() { - return mIntAnimatedValue; - } - - @Override - public IntPropertyValuesHolder clone() { - IntPropertyValuesHolder newPVH = (IntPropertyValuesHolder) super.clone(); - newPVH.mIntKeyframeSet = (IntKeyframeSet) newPVH.mKeyframeSet; - return newPVH; - } - - /** - * Internal function to set the value on the target object, using the setter set up - * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator - * to handle turning the value calculated by ValueAnimator into a value set on the object - * according to the name of the property. - * @param target The target object on which the value is set - */ - @Override - void setAnimatedValue(Object target) { - //if (mIntProperty != null) { - // mIntProperty.setValue(target, mIntAnimatedValue); - // return; - //} - //if (mProperty != null) { - // mProperty.set(target, mIntAnimatedValue); - // return; - //} - //if (mJniSetter != 0) { - // nCallIntMethod(target, mJniSetter, mIntAnimatedValue); - // return; - //} - if (mSetter != null) { - try { - mTmpValueArray[0] = mIntAnimatedValue; - mSetter.invoke(target, mTmpValueArray); - } catch (InvocationTargetException e) { - Log.e("PropertyValuesHolder", e.toString()); - } catch (IllegalAccessException e) { - Log.e("PropertyValuesHolder", e.toString()); - } - } - } - - @Override - void setupSetter(Class targetClass) { - //if (mProperty != null) { - // return; - //} - // Check new static hashmap for setter method - //try { - // mPropertyMapLock.writeLock().lock(); - // HashMap propertyMap = sJNISetterPropertyMap.get(targetClass); - // if (propertyMap != null) { - // Integer mJniSetterInteger = propertyMap.get(mPropertyName); - // if (mJniSetterInteger != null) { - // mJniSetter = mJniSetterInteger; - // } - // } - // if (mJniSetter == 0) { - // String methodName = getMethodName("set", mPropertyName); - // mJniSetter = nGetIntMethod(targetClass, methodName); - // if (mJniSetter != 0) { - // if (propertyMap == null) { - // propertyMap = new HashMap(); - // sJNISetterPropertyMap.put(targetClass, propertyMap); - // } - // propertyMap.put(mPropertyName, mJniSetter); - // } - // } - //} catch (NoSuchMethodError e) { - // Log.d("PropertyValuesHolder", - // "Can't find native method using JNI, use reflection" + e); - //} finally { - // mPropertyMapLock.writeLock().unlock(); - //} - //if (mJniSetter == 0) { - // Couldn't find method through fast JNI approach - just use reflection - super.setupSetter(targetClass); - //} - } - } - - static class FloatPropertyValuesHolder extends PropertyValuesHolder { - - // Cache JNI functions to avoid looking them up twice - //private static final HashMap> sJNISetterPropertyMap = - // new HashMap>(); - //int mJniSetter; - //private FloatProperty mFloatProperty; - - FloatKeyframeSet mFloatKeyframeSet; - float mFloatAnimatedValue; - - public FloatPropertyValuesHolder(String propertyName, FloatKeyframeSet keyframeSet) { - super(propertyName); - mValueType = float.class; - mKeyframeSet = keyframeSet; - mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; - } - - //public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) { - // super(property); - // mValueType = float.class; - // mKeyframeSet = keyframeSet; - // mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; - // if (property instanceof FloatProperty) { - // mFloatProperty = (FloatProperty) mProperty; - // } - //} - - public FloatPropertyValuesHolder(String propertyName, float... values) { - super(propertyName); - setFloatValues(values); - } - - //public FloatPropertyValuesHolder(Property property, float... values) { - // super(property); - // setFloatValues(values); - // if (property instanceof FloatProperty) { - // mFloatProperty = (FloatProperty) mProperty; - // } - //} - - @Override - public void setFloatValues(float... values) { - super.setFloatValues(values); - mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; - } - - @Override - void calculateValue(float fraction) { - mFloatAnimatedValue = mFloatKeyframeSet.getFloatValue(fraction); - } - - @Override - Object getAnimatedValue() { - return mFloatAnimatedValue; - } - - @Override - public FloatPropertyValuesHolder clone() { - FloatPropertyValuesHolder newPVH = (FloatPropertyValuesHolder) super.clone(); - newPVH.mFloatKeyframeSet = (FloatKeyframeSet) newPVH.mKeyframeSet; - return newPVH; - } - - /** - * Internal function to set the value on the target object, using the setter set up - * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator - * to handle turning the value calculated by ValueAnimator into a value set on the object - * according to the name of the property. - * @param target The target object on which the value is set - */ - @Override - void setAnimatedValue(Object target) { - //if (mFloatProperty != null) { - // mFloatProperty.setValue(target, mFloatAnimatedValue); - // return; - //} - //if (mProperty != null) { - // mProperty.set(target, mFloatAnimatedValue); - // return; - //} - //if (mJniSetter != 0) { - // nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue); - // return; - //} - if (mSetter != null) { - try { - mTmpValueArray[0] = mFloatAnimatedValue; - mSetter.invoke(target, mTmpValueArray); - } catch (InvocationTargetException e) { - Log.e("PropertyValuesHolder", e.toString()); - } catch (IllegalAccessException e) { - Log.e("PropertyValuesHolder", e.toString()); - } - } - } - - @Override - void setupSetter(Class targetClass) { - //if (mProperty != null) { - // return; - //} - // Check new static hashmap for setter method - //try { - // mPropertyMapLock.writeLock().lock(); - // HashMap propertyMap = sJNISetterPropertyMap.get(targetClass); - // if (propertyMap != null) { - // Integer mJniSetterInteger = propertyMap.get(mPropertyName); - // if (mJniSetterInteger != null) { - // mJniSetter = mJniSetterInteger; - // } - // } - // if (mJniSetter == 0) { - // String methodName = getMethodName("set", mPropertyName); - // mJniSetter = nGetFloatMethod(targetClass, methodName); - // if (mJniSetter != 0) { - // if (propertyMap == null) { - // propertyMap = new HashMap(); - // sJNISetterPropertyMap.put(targetClass, propertyMap); - // } - // propertyMap.put(mPropertyName, mJniSetter); - // } - // } - //} catch (NoSuchMethodError e) { - // Log.d("PropertyValuesHolder", - // "Can't find native method using JNI, use reflection" + e); - //} finally { - // mPropertyMapLock.writeLock().unlock(); - //} - //if (mJniSetter == 0) { - // Couldn't find method through fast JNI approach - just use reflection - super.setupSetter(targetClass); - //} - } - - } - - //native static private int nGetIntMethod(Class targetClass, String methodName); - //native static private int nGetFloatMethod(Class targetClass, String methodName); - //native static private void nCallIntMethod(Object target, int methodID, int arg); - //native static private void nCallFloatMethod(Object target, int methodID, float arg); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java deleted file mode 100644 index 0ea319244..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -/** - * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators - * allow developers to create animations on arbitrary property types, by allowing them to supply - * custom evaulators for types that are not automatically understood and used by the animation - * system. - * - * @see ValueAnimator#setEvaluator(TypeEvaluator) - */ -public interface TypeEvaluator { - - /** - * This function returns the result of linearly interpolating the start and end values, with - * fraction representing the proportion between the start and end values. The - * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), - * where x0 is startValue, x1 is endValue, - * and t is fraction. - * - * @param fraction The fraction from the starting to the ending values - * @param startValue The start value. - * @param endValue The end value. - * @return A linear interpolation between the start and end values, given the - * fraction parameter. - */ - public T evaluate(float fraction, T startValue, T endValue); - -} \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java deleted file mode 100644 index d8a12c688..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java +++ /dev/null @@ -1,1265 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.nineoldandroids.animation; - -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.AndroidRuntimeException; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * This class provides a simple timing engine for running animations - * which calculate animated values and set them on target objects. - * - *

There is a single timing pulse that all animations use. It runs in a - * custom handler to ensure that property changes happen on the UI thread.

- * - *

By default, ValueAnimator uses non-linear time interpolation, via the - * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates - * out of an animation. This behavior can be changed by calling - * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.

- */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ValueAnimator extends Animator { - - /** - * Internal constants - */ - - /* - * The default amount of time in ms between animation frames - */ - private static final long DEFAULT_FRAME_DELAY = 10; - - /** - * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent - * by the handler to itself to process the next animation frame - */ - static final int ANIMATION_START = 0; - static final int ANIMATION_FRAME = 1; - - /** - * Values used with internal variable mPlayingState to indicate the current state of an - * animation. - */ - static final int STOPPED = 0; // Not yet playing - static final int RUNNING = 1; // Playing normally - static final int SEEKED = 2; // Seeked to some time value - - /** - * Internal variables - * NOTE: This object implements the clone() method, making a deep copy of any referenced - * objects. As other non-trivial fields are added to this class, make sure to add logic - * to clone() to make deep copies of them. - */ - - // The first time that the animation's animateFrame() method is called. This time is used to - // determine elapsed time (and therefore the elapsed fraction) in subsequent calls - // to animateFrame() - long mStartTime; - - /** - * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked - * to a value. - */ - long mSeekTime = -1; - - // TODO: We access the following ThreadLocal variables often, some of them on every update. - // If ThreadLocal access is significantly expensive, we may want to put all of these - // fields into a structure sot hat we just access ThreadLocal once to get the reference - // to that structure, then access the structure directly for each field. - - // The static sAnimationHandler processes the internal timing loop on which all animations - // are based - private static ThreadLocal sAnimationHandler = - new ThreadLocal(); - - // The per-thread list of all active animations - private static final ThreadLocal> sAnimations = - new ThreadLocal>() { - @Override - protected ArrayList initialValue() { - return new ArrayList(); - } - }; - - // The per-thread set of animations to be started on the next animation frame - private static final ThreadLocal> sPendingAnimations = - new ThreadLocal>() { - @Override - protected ArrayList initialValue() { - return new ArrayList(); - } - }; - - /** - * Internal per-thread collections used to avoid set collisions as animations start and end - * while being processed. - */ - private static final ThreadLocal> sDelayedAnims = - new ThreadLocal>() { - @Override - protected ArrayList initialValue() { - return new ArrayList(); - } - }; - - private static final ThreadLocal> sEndingAnims = - new ThreadLocal>() { - @Override - protected ArrayList initialValue() { - return new ArrayList(); - } - }; - - private static final ThreadLocal> sReadyAnims = - new ThreadLocal>() { - @Override - protected ArrayList initialValue() { - return new ArrayList(); - } - }; - - // The time interpolator to be used if none is set on the animation - private static final /*Time*/Interpolator sDefaultInterpolator = - new AccelerateDecelerateInterpolator(); - - // type evaluators for the primitive types handled by this implementation - //private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); - //private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); - - /** - * Used to indicate whether the animation is currently playing in reverse. This causes the - * elapsed fraction to be inverted to calculate the appropriate values. - */ - private boolean mPlayingBackwards = false; - - /** - * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the - * repeatCount (if repeatCount!=INFINITE), the animation ends - */ - private int mCurrentIteration = 0; - - /** - * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction(). - */ - private float mCurrentFraction = 0f; - - /** - * Tracks whether a startDelay'd animation has begun playing through the startDelay. - */ - private boolean mStartedDelay = false; - - /** - * Tracks the time at which the animation began playing through its startDelay. This is - * different from the mStartTime variable, which is used to track when the animation became - * active (which is when the startDelay expired and the animation was added to the active - * animations list). - */ - private long mDelayStartTime; - - /** - * Flag that represents the current state of the animation. Used to figure out when to start - * an animation (if state == STOPPED). Also used to end an animation that - * has been cancel()'d or end()'d since the last animation frame. Possible values are - * STOPPED, RUNNING, SEEKED. - */ - int mPlayingState = STOPPED; - - /** - * Additional playing state to indicate whether an animator has been start()'d. There is - * some lag between a call to start() and the first animation frame. We should still note - * that the animation has been started, even if it's first animation frame has not yet - * happened, and reflect that state in isRunning(). - * Note that delayed animations are different: they are not started until their first - * animation frame, which occurs after their delay elapses. - */ - private boolean mRunning = false; - - /** - * Additional playing state to indicate whether an animator has been start()'d, whether or - * not there is a nonzero startDelay. - */ - private boolean mStarted = false; - - /** - * Flag that denotes whether the animation is set up and ready to go. Used to - * set up animation that has not yet been started. - */ - boolean mInitialized = false; - - // - // Backing variables - // - - // How long the animation should last in ms - private long mDuration = 300; - - // The amount of time in ms to delay starting the animation after start() is called - private long mStartDelay = 0; - - // The number of milliseconds between animation frames - private static long sFrameDelay = DEFAULT_FRAME_DELAY; - - // The number of times the animation will repeat. The default is 0, which means the animation - // will play only once - private int mRepeatCount = 0; - - /** - * The type of repetition that will occur when repeatMode is nonzero. RESTART means the - * animation will start from the beginning on every new cycle. REVERSE means the animation - * will reverse directions on each iteration. - */ - private int mRepeatMode = RESTART; - - /** - * The time interpolator to be used. The elapsed fraction of the animation will be passed - * through this interpolator to calculate the interpolated fraction, which is then used to - * calculate the animated values. - */ - private /*Time*/Interpolator mInterpolator = sDefaultInterpolator; - - /** - * The set of listeners to be sent events through the life of an animation. - */ - private ArrayList mUpdateListeners = null; - - /** - * The property/value sets being animated. - */ - PropertyValuesHolder[] mValues; - - /** - * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values - * by property name during calls to getAnimatedValue(String). - */ - HashMap mValuesMap; - - /** - * Public constants - */ - - /** - * When the animation reaches the end and repeatCount is INFINITE - * or a positive value, the animation restarts from the beginning. - */ - public static final int RESTART = 1; - /** - * When the animation reaches the end and repeatCount is INFINITE - * or a positive value, the animation reverses direction on every iteration. - */ - public static final int REVERSE = 2; - /** - * This value used used with the {@link #setRepeatCount(int)} property to repeat - * the animation indefinitely. - */ - public static final int INFINITE = -1; - - /** - * Creates a new ValueAnimator object. This default constructor is primarily for - * use internally; the factory methods which take parameters are more generally - * useful. - */ - public ValueAnimator() { - } - - /** - * Constructs and returns a ValueAnimator that animates between int values. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. - * - * @param values A set of values that the animation will animate between over time. - * @return A ValueAnimator object that is set up to animate between the given values. - */ - public static ValueAnimator ofInt(int... values) { - ValueAnimator anim = new ValueAnimator(); - anim.setIntValues(values); - return anim; - } - - /** - * Constructs and returns a ValueAnimator that animates between float values. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. - * - * @param values A set of values that the animation will animate between over time. - * @return A ValueAnimator object that is set up to animate between the given values. - */ - public static ValueAnimator ofFloat(float... values) { - ValueAnimator anim = new ValueAnimator(); - anim.setFloatValues(values); - return anim; - } - - /** - * Constructs and returns a ValueAnimator that animates between the values - * specified in the PropertyValuesHolder objects. - * - * @param values A set of PropertyValuesHolder objects whose values will be animated - * between over time. - * @return A ValueAnimator object that is set up to animate between the given values. - */ - public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) { - ValueAnimator anim = new ValueAnimator(); - anim.setValues(values); - return anim; - } - /** - * Constructs and returns a ValueAnimator that animates between Object values. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. - * - *

Since ValueAnimator does not know how to animate between arbitrary Objects, this - * factory method also takes a TypeEvaluator object that the ValueAnimator will use - * to perform that interpolation. - * - * @param evaluator A TypeEvaluator that will be called on each animation frame to - * provide the ncessry interpolation between the Object values to derive the animated - * value. - * @param values A set of values that the animation will animate between over time. - * @return A ValueAnimator object that is set up to animate between the given values. - */ - public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) { - ValueAnimator anim = new ValueAnimator(); - anim.setObjectValues(values); - anim.setEvaluator(evaluator); - return anim; - } - - /** - * Sets int values that will be animated between. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. - * - *

If there are already multiple sets of values defined for this ValueAnimator via more - * than one PropertyValuesHolder object, this method will set the values for the first - * of those objects.

- * - * @param values A set of values that the animation will animate between over time. - */ - public void setIntValues(int... values) { - if (values == null || values.length == 0) { - return; - } - if (mValues == null || mValues.length == 0) { - setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)}); - } else { - PropertyValuesHolder valuesHolder = mValues[0]; - valuesHolder.setIntValues(values); - } - // New property/values/target should cause re-initialization prior to starting - mInitialized = false; - } - - /** - * Sets float values that will be animated between. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. - * - *

If there are already multiple sets of values defined for this ValueAnimator via more - * than one PropertyValuesHolder object, this method will set the values for the first - * of those objects.

- * - * @param values A set of values that the animation will animate between over time. - */ - public void setFloatValues(float... values) { - if (values == null || values.length == 0) { - return; - } - if (mValues == null || mValues.length == 0) { - setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofFloat("", values)}); - } else { - PropertyValuesHolder valuesHolder = mValues[0]; - valuesHolder.setFloatValues(values); - } - // New property/values/target should cause re-initialization prior to starting - mInitialized = false; - } - - /** - * Sets the values to animate between for this animation. A single - * value implies that that value is the one being animated to. However, this is not typically - * useful in a ValueAnimator object because there is no way for the object to determine the - * starting value for the animation (unlike ObjectAnimator, which can derive that value - * from the target object and property being animated). Therefore, there should typically - * be two or more values. - * - *

If there are already multiple sets of values defined for this ValueAnimator via more - * than one PropertyValuesHolder object, this method will set the values for the first - * of those objects.

- * - *

There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate - * between these value objects. ValueAnimator only knows how to interpolate between the - * primitive types specified in the other setValues() methods.

- * - * @param values The set of values to animate between. - */ - public void setObjectValues(Object... values) { - if (values == null || values.length == 0) { - return; - } - if (mValues == null || mValues.length == 0) { - setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofObject("", - (TypeEvaluator)null, values)}); - } else { - PropertyValuesHolder valuesHolder = mValues[0]; - valuesHolder.setObjectValues(values); - } - // New property/values/target should cause re-initialization prior to starting - mInitialized = false; - } - - /** - * Sets the values, per property, being animated between. This function is called internally - * by the constructors of ValueAnimator that take a list of values. But an ValueAnimator can - * be constructed without values and this method can be called to set the values manually - * instead. - * - * @param values The set of values, per property, being animated between. - */ - public void setValues(PropertyValuesHolder... values) { - int numValues = values.length; - mValues = values; - mValuesMap = new HashMap(numValues); - for (int i = 0; i < numValues; ++i) { - PropertyValuesHolder valuesHolder = values[i]; - mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); - } - // New property/values/target should cause re-initialization prior to starting - mInitialized = false; - } - - /** - * Returns the values that this ValueAnimator animates between. These values are stored in - * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list - * of value objects instead. - * - * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the - * values, per property, that define the animation. - */ - public PropertyValuesHolder[] getValues() { - return mValues; - } - - /** - * This function is called immediately before processing the first animation - * frame of an animation. If there is a nonzero startDelay, the - * function is called after that delay ends. - * It takes care of the final initialization steps for the - * animation. - * - *

Overrides of this method should call the superclass method to ensure - * that internal mechanisms for the animation are set up correctly.

- */ - void initAnimation() { - if (!mInitialized) { - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].init(); - } - mInitialized = true; - } - } - - - /** - * Sets the length of the animation. The default duration is 300 milliseconds. - * - * @param duration The length of the animation, in milliseconds. This value cannot - * be negative. - * @return ValueAnimator The object called with setDuration(). This return - * value makes it easier to compose statements together that construct and then set the - * duration, as in ValueAnimator.ofInt(0, 10).setDuration(500).start(). - */ - public ValueAnimator setDuration(long duration) { - if (duration < 0) { - throw new IllegalArgumentException("Animators cannot have negative duration: " + - duration); - } - mDuration = duration; - return this; - } - - /** - * Gets the length of the animation. The default duration is 300 milliseconds. - * - * @return The length of the animation, in milliseconds. - */ - public long getDuration() { - return mDuration; - } - - /** - * Sets the position of the animation to the specified point in time. This time should - * be between 0 and the total duration of the animation, including any repetition. If - * the animation has not yet been started, then it will not advance forward after it is - * set to this time; it will simply set the time to this value and perform any appropriate - * actions based on that time. If the animation is already running, then setCurrentPlayTime() - * will set the current playing time to this value and continue playing from that point. - * - * @param playTime The time, in milliseconds, to which the animation is advanced or rewound. - */ - public void setCurrentPlayTime(long playTime) { - initAnimation(); - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - if (mPlayingState != RUNNING) { - mSeekTime = playTime; - mPlayingState = SEEKED; - } - mStartTime = currentTime - playTime; - animationFrame(currentTime); - } - - /** - * Gets the current position of the animation in time, which is equal to the current - * time minus the time that the animation started. An animation that is not yet started will - * return a value of zero. - * - * @return The current position in time of the animation. - */ - public long getCurrentPlayTime() { - if (!mInitialized || mPlayingState == STOPPED) { - return 0; - } - return AnimationUtils.currentAnimationTimeMillis() - mStartTime; - } - - /** - * This custom, static handler handles the timing pulse that is shared by - * all active animations. This approach ensures that the setting of animation - * values will happen on the UI thread and that all animations will share - * the same times for calculating their values, which makes synchronizing - * animations possible. - * - */ - private static class AnimationHandler extends Handler { - /** - * There are only two messages that we care about: ANIMATION_START and - * ANIMATION_FRAME. The START message is sent when an animation's start() - * method is called. It cannot start synchronously when start() is called - * because the call may be on the wrong thread, and it would also not be - * synchronized with other animations because it would not start on a common - * timing pulse. So each animation sends a START message to the handler, which - * causes the handler to place the animation on the active animations queue and - * start processing frames for that animation. - * The FRAME message is the one that is sent over and over while there are any - * active animations to process. - */ - @Override - public void handleMessage(Message msg) { - boolean callAgain = true; - ArrayList animations = sAnimations.get(); - ArrayList delayedAnims = sDelayedAnims.get(); - switch (msg.what) { - // TODO: should we avoid sending frame message when starting if we - // were already running? - case ANIMATION_START: - ArrayList pendingAnimations = sPendingAnimations.get(); - if (animations.size() > 0 || delayedAnims.size() > 0) { - callAgain = false; - } - // pendingAnims holds any animations that have requested to be started - // We're going to clear sPendingAnimations, but starting animation may - // cause more to be added to the pending list (for example, if one animation - // starting triggers another starting). So we loop until sPendingAnimations - // is empty. - while (pendingAnimations.size() > 0) { - ArrayList pendingCopy = - (ArrayList) pendingAnimations.clone(); - pendingAnimations.clear(); - int count = pendingCopy.size(); - for (int i = 0; i < count; ++i) { - ValueAnimator anim = pendingCopy.get(i); - // If the animation has a startDelay, place it on the delayed list - if (anim.mStartDelay == 0) { - anim.startAnimation(); - } else { - delayedAnims.add(anim); - } - } - } - // fall through to process first frame of new animations - case ANIMATION_FRAME: - // currentTime holds the common time for all animations processed - // during this frame - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - ArrayList readyAnims = sReadyAnims.get(); - ArrayList endingAnims = sEndingAnims.get(); - - // First, process animations currently sitting on the delayed queue, adding - // them to the active animations if they are ready - int numDelayedAnims = delayedAnims.size(); - for (int i = 0; i < numDelayedAnims; ++i) { - ValueAnimator anim = delayedAnims.get(i); - if (anim.delayedAnimationFrame(currentTime)) { - readyAnims.add(anim); - } - } - int numReadyAnims = readyAnims.size(); - if (numReadyAnims > 0) { - for (int i = 0; i < numReadyAnims; ++i) { - ValueAnimator anim = readyAnims.get(i); - anim.startAnimation(); - anim.mRunning = true; - delayedAnims.remove(anim); - } - readyAnims.clear(); - } - - // Now process all active animations. The return value from animationFrame() - // tells the handler whether it should now be ended - int numAnims = animations.size(); - int i = 0; - while (i < numAnims) { - ValueAnimator anim = animations.get(i); - if (anim.animationFrame(currentTime)) { - endingAnims.add(anim); - } - if (animations.size() == numAnims) { - ++i; - } else { - // An animation might be canceled or ended by client code - // during the animation frame. Check to see if this happened by - // seeing whether the current index is the same as it was before - // calling animationFrame(). Another approach would be to copy - // animations to a temporary list and process that list instead, - // but that entails garbage and processing overhead that would - // be nice to avoid. - --numAnims; - endingAnims.remove(anim); - } - } - if (endingAnims.size() > 0) { - for (i = 0; i < endingAnims.size(); ++i) { - endingAnims.get(i).endAnimation(); - } - endingAnims.clear(); - } - - // If there are still active or delayed animations, call the handler again - // after the frameDelay - if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) { - sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay - - (AnimationUtils.currentAnimationTimeMillis() - currentTime))); - } - break; - } - } - } - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - * - * @return the number of milliseconds to delay running the animation - */ - public long getStartDelay() { - return mStartDelay; - } - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - - * @param startDelay The amount of the delay, in milliseconds - */ - public void setStartDelay(long startDelay) { - this.mStartDelay = startDelay; - } - - /** - * The amount of time, in milliseconds, between each frame of the animation. This is a - * requested time that the animation will attempt to honor, but the actual delay between - * frames may be different, depending on system load and capabilities. This is a static - * function because the same delay will be applied to all animations, since they are all - * run off of a single timing loop. - * - * @return the requested time between frames, in milliseconds - */ - public static long getFrameDelay() { - return sFrameDelay; - } - - /** - * The amount of time, in milliseconds, between each frame of the animation. This is a - * requested time that the animation will attempt to honor, but the actual delay between - * frames may be different, depending on system load and capabilities. This is a static - * function because the same delay will be applied to all animations, since they are all - * run off of a single timing loop. - * - * @param frameDelay the requested time between frames, in milliseconds - */ - public static void setFrameDelay(long frameDelay) { - sFrameDelay = frameDelay; - } - - /** - * The most recent value calculated by this ValueAnimator when there is just one - * property being animated. This value is only sensible while the animation is running. The main - * purpose for this read-only property is to retrieve the value from the ValueAnimator - * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which - * is called during each animation frame, immediately after the value is calculated. - * - * @return animatedValue The value most recently calculated by this ValueAnimator for - * the single property being animated. If there are several properties being animated - * (specified by several PropertyValuesHolder objects in the constructor), this function - * returns the animated value for the first of those objects. - */ - public Object getAnimatedValue() { - if (mValues != null && mValues.length > 0) { - return mValues[0].getAnimatedValue(); - } - // Shouldn't get here; should always have values unless ValueAnimator was set up wrong - return null; - } - - /** - * The most recent value calculated by this ValueAnimator for propertyName. - * The main purpose for this read-only property is to retrieve the value from the - * ValueAnimator during a call to - * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which - * is called during each animation frame, immediately after the value is calculated. - * - * @return animatedValue The value most recently calculated for the named property - * by this ValueAnimator. - */ - public Object getAnimatedValue(String propertyName) { - PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName); - if (valuesHolder != null) { - return valuesHolder.getAnimatedValue(); - } else { - // At least avoid crashing if called with bogus propertyName - return null; - } - } - - /** - * Sets how many times the animation should be repeated. If the repeat - * count is 0, the animation is never repeated. If the repeat count is - * greater than 0 or {@link #INFINITE}, the repeat mode will be taken - * into account. The repeat count is 0 by default. - * - * @param value the number of times the animation should be repeated - */ - public void setRepeatCount(int value) { - mRepeatCount = value; - } - /** - * Defines how many times the animation should repeat. The default value - * is 0. - * - * @return the number of times the animation should repeat, or {@link #INFINITE} - */ - public int getRepeatCount() { - return mRepeatCount; - } - - /** - * Defines what this animation should do when it reaches the end. This - * setting is applied only when the repeat count is either greater than - * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. - * - * @param value {@link #RESTART} or {@link #REVERSE} - */ - public void setRepeatMode(int value) { - mRepeatMode = value; - } - - /** - * Defines what this animation should do when it reaches the end. - * - * @return either one of {@link #REVERSE} or {@link #RESTART} - */ - public int getRepeatMode() { - return mRepeatMode; - } - - /** - * Adds a listener to the set of listeners that are sent update events through the life of - * an animation. This method is called on all listeners for every frame of the animation, - * after the values for the animation have been calculated. - * - * @param listener the listener to be added to the current set of listeners for this animation. - */ - public void addUpdateListener(AnimatorUpdateListener listener) { - if (mUpdateListeners == null) { - mUpdateListeners = new ArrayList(); - } - mUpdateListeners.add(listener); - } - - /** - * Removes all listeners from the set listening to frame updates for this animation. - */ - public void removeAllUpdateListeners() { - if (mUpdateListeners == null) { - return; - } - mUpdateListeners.clear(); - mUpdateListeners = null; - } - - /** - * Removes a listener from the set listening to frame updates for this animation. - * - * @param listener the listener to be removed from the current set of update listeners - * for this animation. - */ - public void removeUpdateListener(AnimatorUpdateListener listener) { - if (mUpdateListeners == null) { - return; - } - mUpdateListeners.remove(listener); - if (mUpdateListeners.size() == 0) { - mUpdateListeners = null; - } - } - - - /** - * The time interpolator used in calculating the elapsed fraction of this animation. The - * interpolator determines whether the animation runs with linear or non-linear motion, - * such as acceleration and deceleration. The default value is - * {@link android.view.animation.AccelerateDecelerateInterpolator} - * - * @param value the interpolator to be used by this animation. A value of null - * will result in linear interpolation. - */ - @Override - public void setInterpolator(/*Time*/Interpolator value) { - if (value != null) { - mInterpolator = value; - } else { - mInterpolator = new LinearInterpolator(); - } - } - - /** - * Returns the timing interpolator that this ValueAnimator uses. - * - * @return The timing interpolator for this ValueAnimator. - */ - public /*Time*/Interpolator getInterpolator() { - return mInterpolator; - } - - /** - * The type evaluator to be used when calculating the animated values of this animation. - * The system will automatically assign a float or int evaluator based on the type - * of startValue and endValue in the constructor. But if these values - * are not one of these primitive types, or if different evaluation is desired (such as is - * necessary with int values that represent colors), a custom evaluator needs to be assigned. - * For example, when running an animation on color values, the {@link ArgbEvaluator} - * should be used to get correct RGB color interpolation. - * - *

If this ValueAnimator has only one set of values being animated between, this evaluator - * will be used for that set. If there are several sets of values being animated, which is - * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator - * is assigned just to the first PropertyValuesHolder object.

- * - * @param value the evaluator to be used this animation - */ - public void setEvaluator(TypeEvaluator value) { - if (value != null && mValues != null && mValues.length > 0) { - mValues[0].setEvaluator(value); - } - } - - /** - * Start the animation playing. This version of start() takes a boolean flag that indicates - * whether the animation should play in reverse. The flag is usually false, but may be set - * to true if called from the reverse() method. - * - *

The animation started by calling this method will be run on the thread that called - * this method. This thread should have a Looper on it (a runtime exception will be thrown if - * this is not the case). Also, if the animation will animate - * properties of objects in the view hierarchy, then the calling thread should be the UI - * thread for that view hierarchy.

- * - * @param playBackwards Whether the ValueAnimator should start playing in reverse. - */ - private void start(boolean playBackwards) { - if (Looper.myLooper() == null) { - throw new AndroidRuntimeException("Animators may only be run on Looper threads"); - } - mPlayingBackwards = playBackwards; - mCurrentIteration = 0; - mPlayingState = STOPPED; - mStarted = true; - mStartedDelay = false; - sPendingAnimations.get().add(this); - if (mStartDelay == 0) { - // This sets the initial value of the animation, prior to actually starting it running - setCurrentPlayTime(getCurrentPlayTime()); - mPlayingState = STOPPED; - mRunning = true; - - if (mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - int numListeners = tmpListeners.size(); - for (int i = 0; i < numListeners; ++i) { - tmpListeners.get(i).onAnimationStart(this); - } - } - } - AnimationHandler animationHandler = sAnimationHandler.get(); - if (animationHandler == null) { - animationHandler = new AnimationHandler(); - sAnimationHandler.set(animationHandler); - } - animationHandler.sendEmptyMessage(ANIMATION_START); - } - - @Override - public void start() { - start(false); - } - - @Override - public void cancel() { - // Only cancel if the animation is actually running or has been started and is about - // to run - if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) || - sDelayedAnims.get().contains(this)) { - // Only notify listeners if the animator has actually started - if (mRunning && mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationCancel(this); - } - } - endAnimation(); - } - } - - @Override - public void end() { - if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) { - // Special case if the animation has not yet started; get it ready for ending - mStartedDelay = false; - startAnimation(); - } else if (!mInitialized) { - initAnimation(); - } - // The final value set on the target varies, depending on whether the animation - // was supposed to repeat an odd number of times - if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) { - animateValue(0f); - } else { - animateValue(1f); - } - endAnimation(); - } - - @Override - public boolean isRunning() { - return (mPlayingState == RUNNING || mRunning); - } - - @Override - public boolean isStarted() { - return mStarted; - } - - /** - * Plays the ValueAnimator in reverse. If the animation is already running, - * it will stop itself and play backwards from the point reached when reverse was called. - * If the animation is not currently running, then it will start from the end and - * play backwards. This behavior is only set for the current animation; future playing - * of the animation will use the default behavior of playing forward. - */ - public void reverse() { - mPlayingBackwards = !mPlayingBackwards; - if (mPlayingState == RUNNING) { - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - long currentPlayTime = currentTime - mStartTime; - long timeLeft = mDuration - currentPlayTime; - mStartTime = currentTime - timeLeft; - } else { - start(true); - } - } - - /** - * Called internally to end an animation by removing it from the animations list. Must be - * called on the UI thread. - */ - private void endAnimation() { - sAnimations.get().remove(this); - sPendingAnimations.get().remove(this); - sDelayedAnims.get().remove(this); - mPlayingState = STOPPED; - if (mRunning && mListeners != null) { - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - int numListeners = tmpListeners.size(); - for (int i = 0; i < numListeners; ++i) { - tmpListeners.get(i).onAnimationEnd(this); - } - } - mRunning = false; - mStarted = false; - } - - /** - * Called internally to start an animation by adding it to the active animations list. Must be - * called on the UI thread. - */ - private void startAnimation() { - initAnimation(); - sAnimations.get().add(this); - if (mStartDelay > 0 && mListeners != null) { - // Listeners were already notified in start() if startDelay is 0; this is - // just for delayed animations - ArrayList tmpListeners = - (ArrayList) mListeners.clone(); - int numListeners = tmpListeners.size(); - for (int i = 0; i < numListeners; ++i) { - tmpListeners.get(i).onAnimationStart(this); - } - } - } - - /** - * Internal function called to process an animation frame on an animation that is currently - * sleeping through its startDelay phase. The return value indicates whether it - * should be woken up and put on the active animations queue. - * - * @param currentTime The current animation time, used to calculate whether the animation - * has exceeded its startDelay and should be started. - * @return True if the animation's startDelay has been exceeded and the animation - * should be added to the set of active animations. - */ - private boolean delayedAnimationFrame(long currentTime) { - if (!mStartedDelay) { - mStartedDelay = true; - mDelayStartTime = currentTime; - } else { - long deltaTime = currentTime - mDelayStartTime; - if (deltaTime > mStartDelay) { - // startDelay ended - start the anim and record the - // mStartTime appropriately - mStartTime = currentTime - (deltaTime - mStartDelay); - mPlayingState = RUNNING; - return true; - } - } - return false; - } - - /** - * This internal function processes a single animation frame for a given animation. The - * currentTime parameter is the timing pulse sent by the handler, used to calculate the - * elapsed duration, and therefore - * the elapsed fraction, of the animation. The return value indicates whether the animation - * should be ended (which happens when the elapsed time of the animation exceeds the - * animation's duration, including the repeatCount). - * - * @param currentTime The current time, as tracked by the static timing handler - * @return true if the animation's duration, including any repetitions due to - * repeatCount has been exceeded and the animation should be ended. - */ - boolean animationFrame(long currentTime) { - boolean done = false; - - if (mPlayingState == STOPPED) { - mPlayingState = RUNNING; - if (mSeekTime < 0) { - mStartTime = currentTime; - } else { - mStartTime = currentTime - mSeekTime; - // Now that we're playing, reset the seek time - mSeekTime = -1; - } - } - switch (mPlayingState) { - case RUNNING: - case SEEKED: - float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f; - if (fraction >= 1f) { - if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { - // Time to repeat - if (mListeners != null) { - int numListeners = mListeners.size(); - for (int i = 0; i < numListeners; ++i) { - mListeners.get(i).onAnimationRepeat(this); - } - } - if (mRepeatMode == REVERSE) { - mPlayingBackwards = mPlayingBackwards ? false : true; - } - mCurrentIteration += (int)fraction; - fraction = fraction % 1f; - mStartTime += mDuration; - } else { - done = true; - fraction = Math.min(fraction, 1.0f); - } - } - if (mPlayingBackwards) { - fraction = 1f - fraction; - } - animateValue(fraction); - break; - } - - return done; - } - - /** - * Returns the current animation fraction, which is the elapsed/interpolated fraction used in - * the most recent frame update on the animation. - * - * @return Elapsed/interpolated fraction of the animation. - */ - public float getAnimatedFraction() { - return mCurrentFraction; - } - - /** - * This method is called with the elapsed fraction of the animation during every - * animation frame. This function turns the elapsed fraction into an interpolated fraction - * and then into an animated value (from the evaluator. The function is called mostly during - * animation updates, but it is also called when the end() - * function is called, to set the final value on the property. - * - *

Overrides of this method must call the superclass to perform the calculation - * of the animated value.

- * - * @param fraction The elapsed fraction of the animation. - */ - void animateValue(float fraction) { - fraction = mInterpolator.getInterpolation(fraction); - mCurrentFraction = fraction; - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].calculateValue(fraction); - } - if (mUpdateListeners != null) { - int numListeners = mUpdateListeners.size(); - for (int i = 0; i < numListeners; ++i) { - mUpdateListeners.get(i).onAnimationUpdate(this); - } - } - } - - @Override - public ValueAnimator clone() { - final ValueAnimator anim = (ValueAnimator) super.clone(); - if (mUpdateListeners != null) { - ArrayList oldListeners = mUpdateListeners; - anim.mUpdateListeners = new ArrayList(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mUpdateListeners.add(oldListeners.get(i)); - } - } - anim.mSeekTime = -1; - anim.mPlayingBackwards = false; - anim.mCurrentIteration = 0; - anim.mInitialized = false; - anim.mPlayingState = STOPPED; - anim.mStartedDelay = false; - PropertyValuesHolder[] oldValues = mValues; - if (oldValues != null) { - int numValues = oldValues.length; - anim.mValues = new PropertyValuesHolder[numValues]; - anim.mValuesMap = new HashMap(numValues); - for (int i = 0; i < numValues; ++i) { - PropertyValuesHolder newValuesHolder = oldValues[i].clone(); - anim.mValues[i] = newValuesHolder; - anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder); - } - } - return anim; - } - - /** - * Implementors of this interface can add themselves as update listeners - * to an ValueAnimator instance to receive callbacks on every animation - * frame, after the current frame's values have been calculated for that - * ValueAnimator. - */ - public static interface AnimatorUpdateListener { - /** - *

Notifies the occurrence of another frame of the animation.

- * - * @param animation The animation which was repeated. - */ - void onAnimationUpdate(ValueAnimator animation); - - } - - /** - * Return the number of animations currently running. - * - * Used by StrictMode internally to annotate violations. Only - * called on the main thread. - * - * @hide - */ - public static int getCurrentAnimationsCount() { - return sAnimations.get().size(); - } - - /** - * Clear all animations on this thread, without canceling or ending them. - * This should be used with caution. - * - * @hide - */ - public static void clearAllAnimations() { - sAnimations.get().clear(); - sPendingAnimations.get().clear(); - sDelayedAnims.get().clear(); - } - - @Override - public String toString() { - String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode()); - if (mValues != null) { - for (int i = 0; i < mValues.length; ++i) { - returnVal += "\n " + mValues[i].toString(); - } - } - return returnVal; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java deleted file mode 100644 index 7b830b9c0..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.actionbarsherlock.internal.nineoldandroids.view; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.ViewGroup; - -import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; - -public abstract class NineViewGroup extends ViewGroup { - private final AnimatorProxy mProxy; - - public NineViewGroup(Context context) { - super(context); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } - public NineViewGroup(Context context, AttributeSet attrs) { - super(context, attrs); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } - public NineViewGroup(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } - - @Override - public void setVisibility(int visibility) { - if (mProxy != null) { - if (visibility == GONE) { - clearAnimation(); - } else if (visibility == VISIBLE) { - setAnimation(mProxy); - } - } - super.setVisibility(visibility); - } - - public float getAlpha() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getAlpha(); - } else { - return super.getAlpha(); - } - } - public void setAlpha(float alpha) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setAlpha(alpha); - } else { - super.setAlpha(alpha); - } - } - public float getTranslationX() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getTranslationX(); - } else { - return super.getTranslationX(); - } - } - public void setTranslationX(float translationX) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setTranslationX(translationX); - } else { - super.setTranslationX(translationX); - } - } - public float getTranslationY() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getTranslationY(); - } else { - return super.getTranslationY(); - } - } - public void setTranslationY(float translationY) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setTranslationY(translationY); - } else { - super.setTranslationY(translationY); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java deleted file mode 100644 index 067d0494e..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java +++ /dev/null @@ -1,212 +0,0 @@ -package com.actionbarsherlock.internal.nineoldandroids.view.animation; - -import java.lang.ref.WeakReference; -import java.util.WeakHashMap; -import android.graphics.Matrix; -import android.graphics.RectF; -import android.os.Build; -import android.util.FloatMath; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.Transformation; - -public final class AnimatorProxy extends Animation { - public static final boolean NEEDS_PROXY = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB; - - private static final WeakHashMap PROXIES = - new WeakHashMap(); - - public static AnimatorProxy wrap(View view) { - AnimatorProxy proxy = PROXIES.get(view); - if (proxy == null) { - proxy = new AnimatorProxy(view); - PROXIES.put(view, proxy); - } - return proxy; - } - - private final WeakReference mView; - - private float mAlpha = 1; - private float mScaleX = 1; - private float mScaleY = 1; - private float mTranslationX; - private float mTranslationY; - - private final RectF mBefore = new RectF(); - private final RectF mAfter = new RectF(); - private final Matrix mTempMatrix = new Matrix(); - - private AnimatorProxy(View view) { - setDuration(0); //perform transformation immediately - setFillAfter(true); //persist transformation beyond duration - view.setAnimation(this); - mView = new WeakReference(view); - } - - public float getAlpha() { - return mAlpha; - } - public void setAlpha(float alpha) { - if (mAlpha != alpha) { - mAlpha = alpha; - View view = mView.get(); - if (view != null) { - view.invalidate(); - } - } - } - public float getScaleX() { - return mScaleX; - } - public void setScaleX(float scaleX) { - if (mScaleX != scaleX) { - prepareForUpdate(); - mScaleX = scaleX; - invalidateAfterUpdate(); - } - } - public float getScaleY() { - return mScaleY; - } - public void setScaleY(float scaleY) { - if (mScaleY != scaleY) { - prepareForUpdate(); - mScaleY = scaleY; - invalidateAfterUpdate(); - } - } - public int getScrollX() { - View view = mView.get(); - if (view == null) { - return 0; - } - return view.getScrollX(); - } - public void setScrollX(int value) { - View view = mView.get(); - if (view != null) { - view.scrollTo(value, view.getScrollY()); - } - } - public int getScrollY() { - View view = mView.get(); - if (view == null) { - return 0; - } - return view.getScrollY(); - } - public void setScrollY(int value) { - View view = mView.get(); - if (view != null) { - view.scrollTo(view.getScrollY(), value); - } - } - - public float getTranslationX() { - return mTranslationX; - } - public void setTranslationX(float translationX) { - if (mTranslationX != translationX) { - prepareForUpdate(); - mTranslationX = translationX; - invalidateAfterUpdate(); - } - } - public float getTranslationY() { - return mTranslationY; - } - public void setTranslationY(float translationY) { - if (mTranslationY != translationY) { - prepareForUpdate(); - mTranslationY = translationY; - invalidateAfterUpdate(); - } - } - - private void prepareForUpdate() { - View view = mView.get(); - if (view != null) { - computeRect(mBefore, view); - } - } - private void invalidateAfterUpdate() { - View view = mView.get(); - if (view == null) { - return; - } - View parent = (View)view.getParent(); - if (parent == null) { - return; - } - - view.setAnimation(this); - - final RectF after = mAfter; - computeRect(after, view); - after.union(mBefore); - - parent.invalidate( - (int) FloatMath.floor(after.left), - (int) FloatMath.floor(after.top), - (int) FloatMath.ceil(after.right), - (int) FloatMath.ceil(after.bottom)); - } - - private void computeRect(final RectF r, View view) { - // compute current rectangle according to matrix transformation - final float w = view.getWidth(); - final float h = view.getHeight(); - - // use a rectangle at 0,0 to make sure we don't run into issues with scaling - r.set(0, 0, w, h); - - final Matrix m = mTempMatrix; - m.reset(); - transformMatrix(m, view); - mTempMatrix.mapRect(r); - - r.offset(view.getLeft(), view.getTop()); - - // Straighten coords if rotations flipped them - if (r.right < r.left) { - final float f = r.right; - r.right = r.left; - r.left = f; - } - if (r.bottom < r.top) { - final float f = r.top; - r.top = r.bottom; - r.bottom = f; - } - } - - private void transformMatrix(Matrix m, View view) { - final float w = view.getWidth(); - final float h = view.getHeight(); - - final float sX = mScaleX; - final float sY = mScaleY; - if ((sX != 1.0f) || (sY != 1.0f)) { - final float deltaSX = ((sX * w) - w) / 2f; - final float deltaSY = ((sY * h) - h) / 2f; - m.postScale(sX, sY); - m.postTranslate(-deltaSX, -deltaSY); - } - m.postTranslate(mTranslationX, mTranslationY); - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - View view = mView.get(); - if (view != null) { - t.setAlpha(mAlpha); - transformMatrix(t.getMatrix(), view); - } - } - - @Override - public void reset() { - /* Do nothing. */ - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java deleted file mode 100644 index 953e3e844..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.actionbarsherlock.internal.nineoldandroids.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.FrameLayout; - -import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; - -public class NineFrameLayout extends FrameLayout { - private final AnimatorProxy mProxy; - - public NineFrameLayout(Context context, AttributeSet attrs) { - super(context, attrs); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } - - @Override - public void setVisibility(int visibility) { - if (mProxy != null) { - if (visibility == GONE) { - clearAnimation(); - } else if (visibility == VISIBLE) { - setAnimation(mProxy); - } - } - super.setVisibility(visibility); - } - - public float getAlpha() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getAlpha(); - } else { - return super.getAlpha(); - } - } - public void setAlpha(float alpha) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setAlpha(alpha); - } else { - super.setAlpha(alpha); - } - } - public float getTranslationY() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getTranslationY(); - } else { - return super.getTranslationY(); - } - } - public void setTranslationY(float translationY) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setTranslationY(translationY); - } else { - super.setTranslationY(translationY); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java deleted file mode 100644 index 129b5aaaa..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.actionbarsherlock.internal.nineoldandroids.widget; - -import android.content.Context; -import android.widget.HorizontalScrollView; -import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; - -public class NineHorizontalScrollView extends HorizontalScrollView { - private final AnimatorProxy mProxy; - - public NineHorizontalScrollView(Context context) { - super(context); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } - - @Override - public void setVisibility(int visibility) { - if (mProxy != null) { - if (visibility == GONE) { - clearAnimation(); - } else if (visibility == VISIBLE) { - setAnimation(mProxy); - } - } - super.setVisibility(visibility); - } - - public float getAlpha() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getAlpha(); - } else { - return super.getAlpha(); - } - } - public void setAlpha(float alpha) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setAlpha(alpha); - } else { - super.setAlpha(alpha); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java deleted file mode 100644 index 1f381013a..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.actionbarsherlock.internal.nineoldandroids.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.LinearLayout; - -import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; - -public class NineLinearLayout extends LinearLayout { - private final AnimatorProxy mProxy; - - public NineLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; - } - - @Override - public void setVisibility(int visibility) { - if (mProxy != null) { - if (visibility == GONE) { - clearAnimation(); - } else if (visibility == VISIBLE) { - setAnimation(mProxy); - } - } - super.setVisibility(visibility); - } - - public float getAlpha() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getAlpha(); - } else { - return super.getAlpha(); - } - } - public void setAlpha(float alpha) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setAlpha(alpha); - } else { - super.setAlpha(alpha); - } - } - public float getTranslationX() { - if (AnimatorProxy.NEEDS_PROXY) { - return mProxy.getTranslationX(); - } else { - return super.getTranslationX(); - } - } - public void setTranslationX(float translationX) { - if (AnimatorProxy.NEEDS_PROXY) { - mProxy.setTranslationX(translationX); - } else { - super.setTranslationX(translationX); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java deleted file mode 100644 index b136d50f0..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.actionbarsherlock.internal.view; - -import com.actionbarsherlock.internal.view.menu.SubMenuWrapper; -import com.actionbarsherlock.view.ActionProvider; -import android.view.View; - -public class ActionProviderWrapper extends android.view.ActionProvider { - private final ActionProvider mProvider; - - - public ActionProviderWrapper(ActionProvider provider) { - super(null/*TODO*/); //XXX this *should* be unused - mProvider = provider; - } - - - public ActionProvider unwrap() { - return mProvider; - } - - @Override - public View onCreateActionView() { - return mProvider.onCreateActionView(); - } - - @Override - public boolean hasSubMenu() { - return mProvider.hasSubMenu(); - } - - @Override - public boolean onPerformDefaultAction() { - return mProvider.onPerformDefaultAction(); - } - - @Override - public void onPrepareSubMenu(android.view.SubMenu subMenu) { - mProvider.onPrepareSubMenu(new SubMenuWrapper(subMenu)); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java deleted file mode 100644 index 0a87bd3f7..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.actionbarsherlock.internal.view; - -import android.content.Context; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; - -import java.lang.ref.WeakReference; - -import com.actionbarsherlock.internal.view.menu.MenuBuilder; -import com.actionbarsherlock.internal.view.menu.MenuPopupHelper; -import com.actionbarsherlock.internal.view.menu.SubMenuBuilder; -import com.actionbarsherlock.internal.widget.ActionBarContextView; -import com.actionbarsherlock.view.ActionMode; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuInflater; -import com.actionbarsherlock.view.MenuItem; - -public class StandaloneActionMode extends ActionMode implements MenuBuilder.Callback { - private Context mContext; - private ActionBarContextView mContextView; - private ActionMode.Callback mCallback; - private WeakReference mCustomView; - private boolean mFinished; - private boolean mFocusable; - - private MenuBuilder mMenu; - - public StandaloneActionMode(Context context, ActionBarContextView view, - ActionMode.Callback callback, boolean isFocusable) { - mContext = context; - mContextView = view; - mCallback = callback; - - mMenu = new MenuBuilder(context).setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - mMenu.setCallback(this); - mFocusable = isFocusable; - } - - @Override - public void setTitle(CharSequence title) { - mContextView.setTitle(title); - } - - @Override - public void setSubtitle(CharSequence subtitle) { - mContextView.setSubtitle(subtitle); - } - - @Override - public void setTitle(int resId) { - setTitle(mContext.getString(resId)); - } - - @Override - public void setSubtitle(int resId) { - setSubtitle(mContext.getString(resId)); - } - - @Override - public void setCustomView(View view) { - mContextView.setCustomView(view); - mCustomView = view != null ? new WeakReference(view) : null; - } - - @Override - public void invalidate() { - mCallback.onPrepareActionMode(this, mMenu); - } - - @Override - public void finish() { - if (mFinished) { - return; - } - mFinished = true; - - mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); - mCallback.onDestroyActionMode(this); - } - - @Override - public Menu getMenu() { - return mMenu; - } - - @Override - public CharSequence getTitle() { - return mContextView.getTitle(); - } - - @Override - public CharSequence getSubtitle() { - return mContextView.getSubtitle(); - } - - @Override - public View getCustomView() { - return mCustomView != null ? mCustomView.get() : null; - } - - @Override - public MenuInflater getMenuInflater() { - return new MenuInflater(mContext); - } - - public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { - return mCallback.onActionItemClicked(this, item); - } - - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - } - - public boolean onSubMenuSelected(SubMenuBuilder subMenu) { - if (!subMenu.hasVisibleItems()) { - return true; - } - - new MenuPopupHelper(mContext, subMenu).show(); - return true; - } - - public void onCloseSubMenu(SubMenuBuilder menu) { - } - - public void onMenuModeChange(MenuBuilder menu) { - invalidate(); - mContextView.showOverflowMenu(); - } - - public boolean isUiFocusable() { - return mFocusable; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java deleted file mode 100644 index 7d45e81be..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.actionbarsherlock.internal.view; - -public interface View_HasStateListenerSupport { - void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener); - void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java deleted file mode 100644 index 3869d3290..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.actionbarsherlock.internal.view; - -import android.view.View; - -public interface View_OnAttachStateChangeListener { - void onViewAttachedToWindow(View v); - void onViewDetachedFromWindow(View v); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java deleted file mode 100644 index 0354ad1ad..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import java.util.ArrayList; -import java.util.List; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.view.KeyEvent; - -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -/** - * @hide - */ -public class ActionMenu implements Menu { - private Context mContext; - - private boolean mIsQwerty; - - private ArrayList mItems; - - public ActionMenu(Context context) { - mContext = context; - mItems = new ArrayList(); - } - - public Context getContext() { - return mContext; - } - - public MenuItem add(CharSequence title) { - return add(0, 0, 0, title); - } - - public MenuItem add(int titleRes) { - return add(0, 0, 0, titleRes); - } - - public MenuItem add(int groupId, int itemId, int order, int titleRes) { - return add(groupId, itemId, order, mContext.getResources().getString(titleRes)); - } - - public MenuItem add(int groupId, int itemId, int order, CharSequence title) { - ActionMenuItem item = new ActionMenuItem(getContext(), - groupId, itemId, 0, order, title); - mItems.add(order, item); - return item; - } - - public int addIntentOptions(int groupId, int itemId, int order, - ComponentName caller, Intent[] specifics, Intent intent, int flags, - MenuItem[] outSpecificItems) { - PackageManager pm = mContext.getPackageManager(); - final List lri = - pm.queryIntentActivityOptions(caller, specifics, intent, 0); - final int N = lri != null ? lri.size() : 0; - - if ((flags & FLAG_APPEND_TO_GROUP) == 0) { - removeGroup(groupId); - } - - for (int i=0; i= 0) { - outSpecificItems[ri.specificIndex] = item; - } - } - - return N; - } - - public SubMenu addSubMenu(CharSequence title) { - // TODO Implement submenus - return null; - } - - public SubMenu addSubMenu(int titleRes) { - // TODO Implement submenus - return null; - } - - public SubMenu addSubMenu(int groupId, int itemId, int order, - CharSequence title) { - // TODO Implement submenus - return null; - } - - public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { - // TODO Implement submenus - return null; - } - - public void clear() { - mItems.clear(); - } - - public void close() { - } - - private int findItemIndex(int id) { - final ArrayList items = mItems; - final int itemCount = items.size(); - for (int i = 0; i < itemCount; i++) { - if (items.get(i).getItemId() == id) { - return i; - } - } - - return -1; - } - - public MenuItem findItem(int id) { - return mItems.get(findItemIndex(id)); - } - - public MenuItem getItem(int index) { - return mItems.get(index); - } - - public boolean hasVisibleItems() { - final ArrayList items = mItems; - final int itemCount = items.size(); - - for (int i = 0; i < itemCount; i++) { - if (items.get(i).isVisible()) { - return true; - } - } - - return false; - } - - private ActionMenuItem findItemWithShortcut(int keyCode, KeyEvent event) { - // TODO Make this smarter. - final boolean qwerty = mIsQwerty; - final ArrayList items = mItems; - final int itemCount = items.size(); - - for (int i = 0; i < itemCount; i++) { - ActionMenuItem item = items.get(i); - final char shortcut = qwerty ? item.getAlphabeticShortcut() : - item.getNumericShortcut(); - if (keyCode == shortcut) { - return item; - } - } - return null; - } - - public boolean isShortcutKey(int keyCode, KeyEvent event) { - return findItemWithShortcut(keyCode, event) != null; - } - - public boolean performIdentifierAction(int id, int flags) { - final int index = findItemIndex(id); - if (index < 0) { - return false; - } - - return mItems.get(index).invoke(); - } - - public boolean performShortcut(int keyCode, KeyEvent event, int flags) { - ActionMenuItem item = findItemWithShortcut(keyCode, event); - if (item == null) { - return false; - } - - return item.invoke(); - } - - public void removeGroup(int groupId) { - final ArrayList items = mItems; - int itemCount = items.size(); - int i = 0; - while (i < itemCount) { - if (items.get(i).getGroupId() == groupId) { - items.remove(i); - itemCount--; - } else { - i++; - } - } - } - - public void removeItem(int id) { - mItems.remove(findItemIndex(id)); - } - - public void setGroupCheckable(int group, boolean checkable, - boolean exclusive) { - final ArrayList items = mItems; - final int itemCount = items.size(); - - for (int i = 0; i < itemCount; i++) { - ActionMenuItem item = items.get(i); - if (item.getGroupId() == group) { - item.setCheckable(checkable); - item.setExclusiveCheckable(exclusive); - } - } - } - - public void setGroupEnabled(int group, boolean enabled) { - final ArrayList items = mItems; - final int itemCount = items.size(); - - for (int i = 0; i < itemCount; i++) { - ActionMenuItem item = items.get(i); - if (item.getGroupId() == group) { - item.setEnabled(enabled); - } - } - } - - public void setGroupVisible(int group, boolean visible) { - final ArrayList items = mItems; - final int itemCount = items.size(); - - for (int i = 0; i < itemCount; i++) { - ActionMenuItem item = items.get(i); - if (item.getGroupId() == group) { - item.setVisible(visible); - } - } - } - - public void setQwertyMode(boolean isQwerty) { - mIsQwerty = isQwerty; - } - - public int size() { - return mItems.size(); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java deleted file mode 100644 index 510b97488..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import android.content.Context; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.View; - -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -/** - * @hide - */ -public class ActionMenuItem implements MenuItem { - private final int mId; - private final int mGroup; - //UNUSED private final int mCategoryOrder; - private final int mOrdering; - - private CharSequence mTitle; - private CharSequence mTitleCondensed; - private Intent mIntent; - private char mShortcutNumericChar; - private char mShortcutAlphabeticChar; - - private Drawable mIconDrawable; - //UNUSED private int mIconResId = NO_ICON; - - private Context mContext; - - private MenuItem.OnMenuItemClickListener mClickListener; - - //UNUSED private static final int NO_ICON = 0; - - private int mFlags = ENABLED; - private static final int CHECKABLE = 0x00000001; - private static final int CHECKED = 0x00000002; - private static final int EXCLUSIVE = 0x00000004; - private static final int HIDDEN = 0x00000008; - private static final int ENABLED = 0x00000010; - - public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering, - CharSequence title) { - mContext = context; - mId = id; - mGroup = group; - //UNUSED mCategoryOrder = categoryOrder; - mOrdering = ordering; - mTitle = title; - } - - public char getAlphabeticShortcut() { - return mShortcutAlphabeticChar; - } - - public int getGroupId() { - return mGroup; - } - - public Drawable getIcon() { - return mIconDrawable; - } - - public Intent getIntent() { - return mIntent; - } - - public int getItemId() { - return mId; - } - - public ContextMenuInfo getMenuInfo() { - return null; - } - - public char getNumericShortcut() { - return mShortcutNumericChar; - } - - public int getOrder() { - return mOrdering; - } - - public SubMenu getSubMenu() { - return null; - } - - public CharSequence getTitle() { - return mTitle; - } - - public CharSequence getTitleCondensed() { - return mTitleCondensed; - } - - public boolean hasSubMenu() { - return false; - } - - public boolean isCheckable() { - return (mFlags & CHECKABLE) != 0; - } - - public boolean isChecked() { - return (mFlags & CHECKED) != 0; - } - - public boolean isEnabled() { - return (mFlags & ENABLED) != 0; - } - - public boolean isVisible() { - return (mFlags & HIDDEN) == 0; - } - - public MenuItem setAlphabeticShortcut(char alphaChar) { - mShortcutAlphabeticChar = alphaChar; - return this; - } - - public MenuItem setCheckable(boolean checkable) { - mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0); - return this; - } - - public ActionMenuItem setExclusiveCheckable(boolean exclusive) { - mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0); - return this; - } - - public MenuItem setChecked(boolean checked) { - mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0); - return this; - } - - public MenuItem setEnabled(boolean enabled) { - mFlags = (mFlags & ~ENABLED) | (enabled ? ENABLED : 0); - return this; - } - - public MenuItem setIcon(Drawable icon) { - mIconDrawable = icon; - //UNUSED mIconResId = NO_ICON; - return this; - } - - public MenuItem setIcon(int iconRes) { - //UNUSED mIconResId = iconRes; - mIconDrawable = mContext.getResources().getDrawable(iconRes); - return this; - } - - public MenuItem setIntent(Intent intent) { - mIntent = intent; - return this; - } - - public MenuItem setNumericShortcut(char numericChar) { - mShortcutNumericChar = numericChar; - return this; - } - - public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) { - mClickListener = menuItemClickListener; - return this; - } - - public MenuItem setShortcut(char numericChar, char alphaChar) { - mShortcutNumericChar = numericChar; - mShortcutAlphabeticChar = alphaChar; - return this; - } - - public MenuItem setTitle(CharSequence title) { - mTitle = title; - return this; - } - - public MenuItem setTitle(int title) { - mTitle = mContext.getResources().getString(title); - return this; - } - - public MenuItem setTitleCondensed(CharSequence title) { - mTitleCondensed = title; - return this; - } - - public MenuItem setVisible(boolean visible) { - mFlags = (mFlags & HIDDEN) | (visible ? 0 : HIDDEN); - return this; - } - - public boolean invoke() { - if (mClickListener != null && mClickListener.onMenuItemClick(this)) { - return true; - } - - if (mIntent != null) { - mContext.startActivity(mIntent); - return true; - } - - return false; - } - - public void setShowAsAction(int show) { - // Do nothing. ActionMenuItems always show as action buttons. - } - - public MenuItem setActionView(View actionView) { - throw new UnsupportedOperationException(); - } - - public View getActionView() { - return null; - } - - @Override - public MenuItem setActionView(int resId) { - throw new UnsupportedOperationException(); - } - - @Override - public ActionProvider getActionProvider() { - return null; - } - - @Override - public MenuItem setActionProvider(ActionProvider actionProvider) { - throw new UnsupportedOperationException(); - } - - @Override - public MenuItem setShowAsActionFlags(int actionEnum) { - setShowAsAction(actionEnum); - return this; - } - - @Override - public boolean expandActionView() { - return false; - } - - @Override - public boolean collapseActionView() { - return false; - } - - @Override - public boolean isActionViewExpanded() { - return false; - } - - @Override - public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { - // No need to save the listener; ActionMenuItem does not support collapsing items. - return this; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java deleted file mode 100644 index dcb50f362..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import java.util.HashSet; -import java.util.Set; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.Toast; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.view.View_HasStateListenerSupport; -import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener; -import com.actionbarsherlock.internal.widget.CapitalizingButton; - -import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; - -/** - * @hide - */ -public class ActionMenuItemView extends LinearLayout - implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener, - ActionMenuView.ActionMenuChildView, View_HasStateListenerSupport { - //UNUSED private static final String TAG = "ActionMenuItemView"; - - private MenuItemImpl mItemData; - private CharSequence mTitle; - private MenuBuilder.ItemInvoker mItemInvoker; - - private ImageButton mImageButton; - private CapitalizingButton mTextButton; - private boolean mAllowTextWithIcon; - private boolean mExpandedFormat; - private int mMinWidth; - - private final Set mListeners = new HashSet(); - - public ActionMenuItemView(Context context) { - this(context, null); - } - - public ActionMenuItemView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) { - //TODO super(context, attrs, defStyle); - super(context, attrs); - mAllowTextWithIcon = getResources_getBoolean(context, - R.bool.abs__config_allowActionMenuItemTextWithIcon); - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.SherlockActionMenuItemView, 0, 0); - mMinWidth = a.getDimensionPixelSize( - R.styleable.SherlockActionMenuItemView_android_minWidth, 0); - a.recycle(); - } - - @Override - public void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { - mListeners.add(listener); - } - - @Override - public void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { - mListeners.remove(listener); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - for (View_OnAttachStateChangeListener listener : mListeners) { - listener.onViewAttachedToWindow(this); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - for (View_OnAttachStateChangeListener listener : mListeners) { - listener.onViewDetachedFromWindow(this); - } - } - - @Override - public void onFinishInflate() { - - mImageButton = (ImageButton) findViewById(R.id.abs__imageButton); - mTextButton = (CapitalizingButton) findViewById(R.id.abs__textButton); - mImageButton.setOnClickListener(this); - mTextButton.setOnClickListener(this); - mImageButton.setOnLongClickListener(this); - setOnClickListener(this); - setOnLongClickListener(this); - } - - public MenuItemImpl getItemData() { - return mItemData; - } - - public void initialize(MenuItemImpl itemData, int menuType) { - mItemData = itemData; - - setIcon(itemData.getIcon()); - setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon - setId(itemData.getItemId()); - - setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); - setEnabled(itemData.isEnabled()); - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - mImageButton.setEnabled(enabled); - mTextButton.setEnabled(enabled); - } - - public void onClick(View v) { - if (mItemInvoker != null) { - mItemInvoker.invokeItem(mItemData); - } - } - - public void setItemInvoker(MenuBuilder.ItemInvoker invoker) { - mItemInvoker = invoker; - } - - public boolean prefersCondensedTitle() { - return true; - } - - public void setCheckable(boolean checkable) { - // TODO Support checkable action items - } - - public void setChecked(boolean checked) { - // TODO Support checkable action items - } - - public void setExpandedFormat(boolean expandedFormat) { - if (mExpandedFormat != expandedFormat) { - mExpandedFormat = expandedFormat; - if (mItemData != null) { - mItemData.actionFormatChanged(); - } - } - } - - private void updateTextButtonVisibility() { - boolean visible = !TextUtils.isEmpty(mTextButton.getText()); - visible &= mImageButton.getDrawable() == null || - (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat)); - - mTextButton.setVisibility(visible ? VISIBLE : GONE); - } - - public void setIcon(Drawable icon) { - mImageButton.setImageDrawable(icon); - if (icon != null) { - mImageButton.setVisibility(VISIBLE); - } else { - mImageButton.setVisibility(GONE); - } - - updateTextButtonVisibility(); - } - - public boolean hasText() { - return mTextButton.getVisibility() != GONE; - } - - public void setShortcut(boolean showShortcut, char shortcutKey) { - // Action buttons don't show text for shortcut keys. - } - - public void setTitle(CharSequence title) { - mTitle = title; - - mTextButton.setTextCompat(mTitle); - - setContentDescription(mTitle); - updateTextButtonVisibility(); - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - onPopulateAccessibilityEvent(event); - return true; - } - - @Override - public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - super.onPopulateAccessibilityEvent(event); - } - final CharSequence cdesc = getContentDescription(); - if (!TextUtils.isEmpty(cdesc)) { - event.getText().add(cdesc); - } - } - - @Override - public boolean dispatchHoverEvent(MotionEvent event) { - // Don't allow children to hover; we want this to be treated as a single component. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return onHoverEvent(event); - } - return false; - } - - public boolean showsIcon() { - return true; - } - - public boolean needsDividerBefore() { - return hasText() && mItemData.getIcon() == null; - } - - public boolean needsDividerAfter() { - return hasText(); - } - - @Override - public boolean onLongClick(View v) { - if (hasText()) { - // Don't show the cheat sheet for items that already show text. - return false; - } - - final int[] screenPos = new int[2]; - final Rect displayFrame = new Rect(); - getLocationOnScreen(screenPos); - getWindowVisibleDisplayFrame(displayFrame); - - final Context context = getContext(); - final int width = getWidth(); - final int height = getHeight(); - final int midy = screenPos[1] + height / 2; - final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; - - Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT); - if (midy < displayFrame.height()) { - // Show along the top; follow action buttons - cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT, - screenWidth - screenPos[0] - width / 2, height); - } else { - // Show along the bottom center - cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height); - } - cheatSheet.show(); - return true; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - final int specSize = MeasureSpec.getSize(widthMeasureSpec); - final int oldMeasuredWidth = getMeasuredWidth(); - final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(specSize, mMinWidth) - : mMinWidth; - - if (widthMode != MeasureSpec.EXACTLY && mMinWidth > 0 && oldMeasuredWidth < targetWidth) { - // Remeasure at exactly the minimum width. - super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), - heightMeasureSpec); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java deleted file mode 100644 index 876a22c58..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java +++ /dev/null @@ -1,714 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getInteger; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.SparseBooleanArray; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.ImageButton; -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.view.View_HasStateListenerSupport; -import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener; -import com.actionbarsherlock.internal.view.menu.ActionMenuView.ActionMenuChildView; -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.view.MenuItem; - -/** - * MenuPresenter for building action menus as seen in the action bar and action modes. - */ -public class ActionMenuPresenter extends BaseMenuPresenter - implements ActionProvider.SubUiVisibilityListener { - //UNUSED private static final String TAG = "ActionMenuPresenter"; - - private View mOverflowButton; - private boolean mReserveOverflow; - private boolean mReserveOverflowSet; - private int mWidthLimit; - private int mActionItemWidthLimit; - private int mMaxItems; - private boolean mMaxItemsSet; - private boolean mStrictWidthLimit; - private boolean mWidthLimitSet; - private boolean mExpandedActionViewsExclusive; - - private int mMinCellSize; - - // Group IDs that have been added as actions - used temporarily, allocated here for reuse. - private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray(); - - private View mScrapActionButtonView; - - private OverflowPopup mOverflowPopup; - private ActionButtonSubmenu mActionButtonPopup; - - private OpenOverflowRunnable mPostedOpenRunnable; - - final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback(); - int mOpenSubMenuId; - - public ActionMenuPresenter(Context context) { - super(context, R.layout.abs__action_menu_layout, - R.layout.abs__action_menu_item_layout); - } - - @Override - public void initForMenu(Context context, MenuBuilder menu) { - super.initForMenu(context, menu); - - final Resources res = context.getResources(); - - if (!mReserveOverflowSet) { - mReserveOverflow = reserveOverflow(mContext); - } - - if (!mWidthLimitSet) { - mWidthLimit = res.getDisplayMetrics().widthPixels / 2; - } - - // Measure for initial configuration - if (!mMaxItemsSet) { - mMaxItems = getResources_getInteger(context, R.integer.abs__max_action_buttons); - } - - int width = mWidthLimit; - if (mReserveOverflow) { - if (mOverflowButton == null) { - mOverflowButton = new OverflowMenuButton(mSystemContext); - final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - mOverflowButton.measure(spec, spec); - } - width -= mOverflowButton.getMeasuredWidth(); - } else { - mOverflowButton = null; - } - - mActionItemWidthLimit = width; - - mMinCellSize = (int) (ActionMenuView.MIN_CELL_SIZE * res.getDisplayMetrics().density); - - // Drop a scrap view as it may no longer reflect the proper context/config. - mScrapActionButtonView = null; - } - - public static boolean reserveOverflow(Context context) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB); - } else { - return !HasPermanentMenuKey.get(context); - } - } - - private static class HasPermanentMenuKey { - public static boolean get(Context context) { - return ViewConfiguration.get(context).hasPermanentMenuKey(); - } - } - - public void onConfigurationChanged(Configuration newConfig) { - if (!mMaxItemsSet) { - mMaxItems = getResources_getInteger(mContext, - R.integer.abs__max_action_buttons); - if (mMenu != null) { - mMenu.onItemsChanged(true); - } - } - } - - public void setWidthLimit(int width, boolean strict) { - mWidthLimit = width; - mStrictWidthLimit = strict; - mWidthLimitSet = true; - } - - public void setReserveOverflow(boolean reserveOverflow) { - mReserveOverflow = reserveOverflow; - mReserveOverflowSet = true; - } - - public void setItemLimit(int itemCount) { - mMaxItems = itemCount; - mMaxItemsSet = true; - } - - public void setExpandedActionViewsExclusive(boolean isExclusive) { - mExpandedActionViewsExclusive = isExclusive; - } - - @Override - public MenuView getMenuView(ViewGroup root) { - MenuView result = super.getMenuView(root); - ((ActionMenuView) result).setPresenter(this); - return result; - } - - @Override - public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) { - View actionView = item.getActionView(); - if (actionView == null || item.hasCollapsibleActionView()) { - if (!(convertView instanceof ActionMenuItemView)) { - convertView = null; - } - actionView = super.getItemView(item, convertView, parent); - } - actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE); - - final ActionMenuView menuParent = (ActionMenuView) parent; - final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); - if (!menuParent.checkLayoutParams(lp)) { - actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); - } - return actionView; - } - - @Override - public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) { - itemView.initialize(item, 0); - - final ActionMenuView menuView = (ActionMenuView) mMenuView; - ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; - actionItemView.setItemInvoker(menuView); - } - - @Override - public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) { - return item.isActionButton(); - } - - @Override - public void updateMenuView(boolean cleared) { - super.updateMenuView(cleared); - - if (mMenu != null) { - final ArrayList actionItems = mMenu.getActionItems(); - final int count = actionItems.size(); - for (int i = 0; i < count; i++) { - final ActionProvider provider = actionItems.get(i).getActionProvider(); - if (provider != null) { - provider.setSubUiVisibilityListener(this); - } - } - } - - final ArrayList nonActionItems = mMenu != null ? - mMenu.getNonActionItems() : null; - - boolean hasOverflow = false; - if (mReserveOverflow && nonActionItems != null) { - final int count = nonActionItems.size(); - if (count == 1) { - hasOverflow = !nonActionItems.get(0).isActionViewExpanded(); - } else { - hasOverflow = count > 0; - } - } - - if (hasOverflow) { - if (mOverflowButton == null) { - mOverflowButton = new OverflowMenuButton(mSystemContext); - } - ViewGroup parent = (ViewGroup) mOverflowButton.getParent(); - if (parent != mMenuView) { - if (parent != null) { - parent.removeView(mOverflowButton); - } - ActionMenuView menuView = (ActionMenuView) mMenuView; - menuView.addView(mOverflowButton, menuView.generateOverflowButtonLayoutParams()); - } - } else if (mOverflowButton != null && mOverflowButton.getParent() == mMenuView) { - ((ViewGroup) mMenuView).removeView(mOverflowButton); - } - - ((ActionMenuView) mMenuView).setOverflowReserved(mReserveOverflow); - } - - @Override - public boolean filterLeftoverView(ViewGroup parent, int childIndex) { - if (parent.getChildAt(childIndex) == mOverflowButton) return false; - return super.filterLeftoverView(parent, childIndex); - } - - public boolean onSubMenuSelected(SubMenuBuilder subMenu) { - if (!subMenu.hasVisibleItems()) return false; - - SubMenuBuilder topSubMenu = subMenu; - while (topSubMenu.getParentMenu() != mMenu) { - topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu(); - } - View anchor = findViewForItem(topSubMenu.getItem()); - if (anchor == null) { - if (mOverflowButton == null) return false; - anchor = mOverflowButton; - } - - mOpenSubMenuId = subMenu.getItem().getItemId(); - mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu); - mActionButtonPopup.setAnchorView(anchor); - mActionButtonPopup.show(); - super.onSubMenuSelected(subMenu); - return true; - } - - private View findViewForItem(MenuItem item) { - final ViewGroup parent = (ViewGroup) mMenuView; - if (parent == null) return null; - - final int count = parent.getChildCount(); - for (int i = 0; i < count; i++) { - final View child = parent.getChildAt(i); - if (child instanceof MenuView.ItemView && - ((MenuView.ItemView) child).getItemData() == item) { - return child; - } - } - return null; - } - - /** - * Display the overflow menu if one is present. - * @return true if the overflow menu was shown, false otherwise. - */ - public boolean showOverflowMenu() { - if (mReserveOverflow && !isOverflowMenuShowing() && mMenu != null && mMenuView != null && - mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) { - OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true); - mPostedOpenRunnable = new OpenOverflowRunnable(popup); - // Post this for later; we might still need a layout for the anchor to be right. - ((View) mMenuView).post(mPostedOpenRunnable); - - // ActionMenuPresenter uses null as a callback argument here - // to indicate overflow is opening. - super.onSubMenuSelected(null); - - return true; - } - return false; - } - - /** - * Hide the overflow menu if it is currently showing. - * - * @return true if the overflow menu was hidden, false otherwise. - */ - public boolean hideOverflowMenu() { - if (mPostedOpenRunnable != null && mMenuView != null) { - ((View) mMenuView).removeCallbacks(mPostedOpenRunnable); - mPostedOpenRunnable = null; - return true; - } - - MenuPopupHelper popup = mOverflowPopup; - if (popup != null) { - popup.dismiss(); - return true; - } - return false; - } - - /** - * Dismiss all popup menus - overflow and submenus. - * @return true if popups were dismissed, false otherwise. (This can be because none were open.) - */ - public boolean dismissPopupMenus() { - boolean result = hideOverflowMenu(); - result |= hideSubMenus(); - return result; - } - - /** - * Dismiss all submenu popups. - * - * @return true if popups were dismissed, false otherwise. (This can be because none were open.) - */ - public boolean hideSubMenus() { - if (mActionButtonPopup != null) { - mActionButtonPopup.dismiss(); - return true; - } - return false; - } - - /** - * @return true if the overflow menu is currently showing - */ - public boolean isOverflowMenuShowing() { - return mOverflowPopup != null && mOverflowPopup.isShowing(); - } - - /** - * @return true if space has been reserved in the action menu for an overflow item. - */ - public boolean isOverflowReserved() { - return mReserveOverflow; - } - - public boolean flagActionItems() { - final ArrayList visibleItems = mMenu.getVisibleItems(); - final int itemsSize = visibleItems.size(); - int maxActions = mMaxItems; - int widthLimit = mActionItemWidthLimit; - final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final ViewGroup parent = (ViewGroup) mMenuView; - - int requiredItems = 0; - int requestedItems = 0; - int firstActionWidth = 0; - boolean hasOverflow = false; - for (int i = 0; i < itemsSize; i++) { - MenuItemImpl item = visibleItems.get(i); - if (item.requiresActionButton()) { - requiredItems++; - } else if (item.requestsActionButton()) { - requestedItems++; - } else { - hasOverflow = true; - } - if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) { - // Overflow everything if we have an expanded action view and we're - // space constrained. - maxActions = 0; - } - } - - // Reserve a spot for the overflow item if needed. - if (mReserveOverflow && - (hasOverflow || requiredItems + requestedItems > maxActions)) { - maxActions--; - } - maxActions -= requiredItems; - - final SparseBooleanArray seenGroups = mActionButtonGroups; - seenGroups.clear(); - - int cellSize = 0; - int cellsRemaining = 0; - if (mStrictWidthLimit) { - cellsRemaining = widthLimit / mMinCellSize; - final int cellSizeRemaining = widthLimit % mMinCellSize; - cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining; - } - - // Flag as many more requested items as will fit. - for (int i = 0; i < itemsSize; i++) { - MenuItemImpl item = visibleItems.get(i); - - if (item.requiresActionButton()) { - View v = getItemView(item, mScrapActionButtonView, parent); - if (mScrapActionButtonView == null) { - mScrapActionButtonView = v; - } - if (mStrictWidthLimit) { - cellsRemaining -= ActionMenuView.measureChildForCells(v, - cellSize, cellsRemaining, querySpec, 0); - } else { - v.measure(querySpec, querySpec); - } - final int measuredWidth = v.getMeasuredWidth(); - widthLimit -= measuredWidth; - if (firstActionWidth == 0) { - firstActionWidth = measuredWidth; - } - final int groupId = item.getGroupId(); - if (groupId != 0) { - seenGroups.put(groupId, true); - } - item.setIsActionButton(true); - } else if (item.requestsActionButton()) { - // Items in a group with other items that already have an action slot - // can break the max actions rule, but not the width limit. - final int groupId = item.getGroupId(); - final boolean inGroup = seenGroups.get(groupId); - boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 && - (!mStrictWidthLimit || cellsRemaining > 0); - - if (isAction) { - View v = getItemView(item, mScrapActionButtonView, parent); - if (mScrapActionButtonView == null) { - mScrapActionButtonView = v; - } - if (mStrictWidthLimit) { - final int cells = ActionMenuView.measureChildForCells(v, - cellSize, cellsRemaining, querySpec, 0); - cellsRemaining -= cells; - if (cells == 0) { - isAction = false; - } - } else { - v.measure(querySpec, querySpec); - } - final int measuredWidth = v.getMeasuredWidth(); - widthLimit -= measuredWidth; - if (firstActionWidth == 0) { - firstActionWidth = measuredWidth; - } - - if (mStrictWidthLimit) { - isAction &= widthLimit >= 0; - } else { - // Did this push the entire first item past the limit? - isAction &= widthLimit + firstActionWidth > 0; - } - } - - if (isAction && groupId != 0) { - seenGroups.put(groupId, true); - } else if (inGroup) { - // We broke the width limit. Demote the whole group, they all overflow now. - seenGroups.put(groupId, false); - for (int j = 0; j < i; j++) { - MenuItemImpl areYouMyGroupie = visibleItems.get(j); - if (areYouMyGroupie.getGroupId() == groupId) { - // Give back the action slot - if (areYouMyGroupie.isActionButton()) maxActions++; - areYouMyGroupie.setIsActionButton(false); - } - } - } - - if (isAction) maxActions--; - - item.setIsActionButton(isAction); - } - } - return true; - } - - @Override - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - dismissPopupMenus(); - super.onCloseMenu(menu, allMenusAreClosing); - } - - @Override - public Parcelable onSaveInstanceState() { - SavedState state = new SavedState(); - state.openSubMenuId = mOpenSubMenuId; - return state; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState saved = (SavedState) state; - if (saved.openSubMenuId > 0) { - MenuItem item = mMenu.findItem(saved.openSubMenuId); - if (item != null) { - SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); - onSubMenuSelected(subMenu); - } - } - } - - @Override - public void onSubUiVisibilityChanged(boolean isVisible) { - if (isVisible) { - // Not a submenu, but treat it like one. - super.onSubMenuSelected(null); - } else { - mMenu.close(false); - } - } - - private static class SavedState implements Parcelable { - public int openSubMenuId; - - SavedState() { - } - - SavedState(Parcel in) { - openSubMenuId = in.readInt(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(openSubMenuId); - } - - @SuppressWarnings("unused") - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - private class OverflowMenuButton extends ImageButton implements ActionMenuChildView, View_HasStateListenerSupport { - private final Set mListeners = new HashSet(); - - public OverflowMenuButton(Context context) { - super(context, null, R.attr.actionOverflowButtonStyle); - - setClickable(true); - setFocusable(true); - setVisibility(VISIBLE); - setEnabled(true); - } - - @Override - public boolean performClick() { - if (super.performClick()) { - return true; - } - - playSoundEffect(SoundEffectConstants.CLICK); - showOverflowMenu(); - return true; - } - - public boolean needsDividerBefore() { - return false; - } - - public boolean needsDividerAfter() { - return false; - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - for (View_OnAttachStateChangeListener listener : mListeners) { - listener.onViewAttachedToWindow(this); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - for (View_OnAttachStateChangeListener listener : mListeners) { - listener.onViewDetachedFromWindow(this); - } - - if (mOverflowPopup != null) mOverflowPopup.dismiss(); - } - - @Override - public void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { - mListeners.add(listener); - } - - @Override - public void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { - mListeners.remove(listener); - } - } - - private class OverflowPopup extends MenuPopupHelper { - public OverflowPopup(Context context, MenuBuilder menu, View anchorView, - boolean overflowOnly) { - super(context, menu, anchorView, overflowOnly); - setCallback(mPopupPresenterCallback); - } - - @Override - public void onDismiss() { - super.onDismiss(); - mMenu.close(); - mOverflowPopup = null; - } - } - - private class ActionButtonSubmenu extends MenuPopupHelper { - //UNUSED private SubMenuBuilder mSubMenu; - - public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) { - super(context, subMenu); - //UNUSED mSubMenu = subMenu; - - MenuItemImpl item = (MenuItemImpl) subMenu.getItem(); - if (!item.isActionButton()) { - // Give a reasonable anchor to nested submenus. - setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton); - } - - setCallback(mPopupPresenterCallback); - - boolean preserveIconSpacing = false; - final int count = subMenu.size(); - for (int i = 0; i < count; i++) { - MenuItem childItem = subMenu.getItem(i); - if (childItem.isVisible() && childItem.getIcon() != null) { - preserveIconSpacing = true; - break; - } - } - setForceShowIcon(preserveIconSpacing); - } - - @Override - public void onDismiss() { - super.onDismiss(); - mActionButtonPopup = null; - mOpenSubMenuId = 0; - } - } - - private class PopupPresenterCallback implements MenuPresenter.Callback { - - @Override - public boolean onOpenSubMenu(MenuBuilder subMenu) { - if (subMenu == null) return false; - - mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); - return false; - } - - @Override - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - if (menu instanceof SubMenuBuilder) { - ((SubMenuBuilder) menu).getRootMenu().close(false); - } - } - } - - private class OpenOverflowRunnable implements Runnable { - private OverflowPopup mPopup; - - public OpenOverflowRunnable(OverflowPopup popup) { - mPopup = popup; - } - - public void run() { - mMenu.changeMenuMode(); - final View menuView = (View) mMenuView; - if (menuView != null && menuView.getWindowToken() != null && mPopup.tryShow()) { - mOverflowPopup = mPopup; - } - mPostedOpenRunnable = null; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java deleted file mode 100644 index 0e3b1ae0d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.actionbarsherlock.internal.view.menu; - -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.os.Build; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; -import android.widget.LinearLayout; -import com.actionbarsherlock.internal.widget.IcsLinearLayout; - -/** - * @hide - */ -public class ActionMenuView extends IcsLinearLayout implements MenuBuilder.ItemInvoker, MenuView { - //UNUSED private static final String TAG = "ActionMenuView"; - private static final boolean IS_FROYO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; - - static final int MIN_CELL_SIZE = 56; // dips - static final int GENERATED_ITEM_PADDING = 4; // dips - - private MenuBuilder mMenu; - - private boolean mReserveOverflow; - private ActionMenuPresenter mPresenter; - private boolean mFormatItems; - private int mFormatItemsWidth; - private int mMinCellSize; - private int mGeneratedItemPadding; - //UNUSED private int mMeasuredExtraWidth; - - private boolean mFirst = true; - - public ActionMenuView(Context context) { - this(context, null); - } - - public ActionMenuView(Context context, AttributeSet attrs) { - super(context, attrs); - setBaselineAligned(false); - final float density = context.getResources().getDisplayMetrics().density; - mMinCellSize = (int) (MIN_CELL_SIZE * density); - mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density); - } - - public void setPresenter(ActionMenuPresenter presenter) { - mPresenter = presenter; - } - - public boolean isExpandedFormat() { - return mFormatItems; - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - if (IS_FROYO) { - super.onConfigurationChanged(newConfig); - } - mPresenter.updateMenuView(false); - - if (mPresenter != null && mPresenter.isOverflowMenuShowing()) { - mPresenter.hideOverflowMenu(); - mPresenter.showOverflowMenu(); - } - } - - @Override - protected void onDraw(Canvas canvas) { - //Need to trigger a relayout since we may have been added extremely - //late in the initial rendering (e.g., when contained in a ViewPager). - //See: https://github.com/JakeWharton/ActionBarSherlock/issues/272 - if (!IS_FROYO && mFirst) { - mFirst = false; - requestLayout(); - return; - } - super.onDraw(canvas); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // If we've been given an exact size to match, apply special formatting during layout. - final boolean wasFormatted = mFormatItems; - mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; - - if (wasFormatted != mFormatItems) { - mFormatItemsWidth = 0; // Reset this when switching modes - } - - // Special formatting can change whether items can fit as action buttons. - // Kick the menu and update presenters when this changes. - final int widthSize = MeasureSpec.getMode(widthMeasureSpec); - if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) { - mFormatItemsWidth = widthSize; - mMenu.onItemsChanged(true); - } - - if (mFormatItems) { - onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec); - } else { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) { - // We already know the width mode is EXACTLY if we're here. - final int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - final int widthPadding = getPaddingLeft() + getPaddingRight(); - final int heightPadding = getPaddingTop() + getPaddingBottom(); - - widthSize -= widthPadding; - - // Divide the view into cells. - final int cellCount = widthSize / mMinCellSize; - final int cellSizeRemaining = widthSize % mMinCellSize; - - if (cellCount == 0) { - // Give up, nothing fits. - setMeasuredDimension(widthSize, 0); - return; - } - - final int cellSize = mMinCellSize + cellSizeRemaining / cellCount; - - int cellsRemaining = cellCount; - int maxChildHeight = 0; - int maxCellsUsed = 0; - int expandableItemCount = 0; - int visibleItemCount = 0; - boolean hasOverflow = false; - - // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64. - long smallestItemsAt = 0; - - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - if (child.getVisibility() == GONE) continue; - - final boolean isGeneratedItem = child instanceof ActionMenuItemView; - visibleItemCount++; - - if (isGeneratedItem) { - // Reset padding for generated menu item views; it may change below - // and views are recycled. - child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0); - } - - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - lp.expanded = false; - lp.extraPixels = 0; - lp.cellsUsed = 0; - lp.expandable = false; - lp.leftMargin = 0; - lp.rightMargin = 0; - lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText(); - - // Overflow always gets 1 cell. No more, no less. - final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining; - - final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, - heightMeasureSpec, heightPadding); - - maxCellsUsed = Math.max(maxCellsUsed, cellsUsed); - if (lp.expandable) expandableItemCount++; - if (lp.isOverflowButton) hasOverflow = true; - - cellsRemaining -= cellsUsed; - maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); - if (cellsUsed == 1) smallestItemsAt |= (1 << i); - } - - // When we have overflow and a single expanded (text) item, we want to try centering it - // visually in the available space even though overflow consumes some of it. - final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2; - - // Divide space for remaining cells if we have items that can expand. - // Try distributing whole leftover cells to smaller items first. - - boolean needsExpansion = false; - while (expandableItemCount > 0 && cellsRemaining > 0) { - int minCells = Integer.MAX_VALUE; - long minCellsAt = 0; // Bit locations are indices of relevant child views - int minCellsItemCount = 0; - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - // Don't try to expand items that shouldn't. - if (!lp.expandable) continue; - - // Mark indices of children that can receive an extra cell. - if (lp.cellsUsed < minCells) { - minCells = lp.cellsUsed; - minCellsAt = 1 << i; - minCellsItemCount = 1; - } else if (lp.cellsUsed == minCells) { - minCellsAt |= 1 << i; - minCellsItemCount++; - } - } - - // Items that get expanded will always be in the set of smallest items when we're done. - smallestItemsAt |= minCellsAt; - - if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop. - - // We have enough cells, all minimum size items will be incremented. - minCells++; - - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if ((minCellsAt & (1 << i)) == 0) { - // If this item is already at our small item count, mark it for later. - if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i; - continue; - } - - if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) { - // Add padding to this item such that it centers. - child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0); - } - lp.cellsUsed++; - lp.expanded = true; - cellsRemaining--; - } - - needsExpansion = true; - } - - // Divide any space left that wouldn't divide along cell boundaries - // evenly among the smallest items - - final boolean singleItem = !hasOverflow && visibleItemCount == 1; - if (cellsRemaining > 0 && smallestItemsAt != 0 && - (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) { - float expandCount = Long.bitCount(smallestItemsAt); - - if (!singleItem) { - // The items at the far edges may only expand by half in order to pin to either side. - if ((smallestItemsAt & 1) != 0) { - LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams(); - if (!lp.preventEdgeOffset) expandCount -= 0.5f; - } - if ((smallestItemsAt & (1 << (childCount - 1))) != 0) { - LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams()); - if (!lp.preventEdgeOffset) expandCount -= 0.5f; - } - } - - final int extraPixels = expandCount > 0 ? - (int) (cellsRemaining * cellSize / expandCount) : 0; - - for (int i = 0; i < childCount; i++) { - if ((smallestItemsAt & (1 << i)) == 0) continue; - - final View child = getChildAt(i); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (child instanceof ActionMenuItemView) { - // If this is one of our views, expand and measure at the larger size. - lp.extraPixels = extraPixels; - lp.expanded = true; - if (i == 0 && !lp.preventEdgeOffset) { - // First item gets part of its new padding pushed out of sight. - // The last item will get this implicitly from layout. - lp.leftMargin = -extraPixels / 2; - } - needsExpansion = true; - } else if (lp.isOverflowButton) { - lp.extraPixels = extraPixels; - lp.expanded = true; - lp.rightMargin = -extraPixels / 2; - needsExpansion = true; - } else { - // If we don't know what it is, give it some margins instead - // and let it center within its space. We still want to pin - // against the edges. - if (i != 0) { - lp.leftMargin = extraPixels / 2; - } - if (i != childCount - 1) { - lp.rightMargin = extraPixels / 2; - } - } - } - - cellsRemaining = 0; - } - - // Remeasure any items that have had extra space allocated to them. - if (needsExpansion) { - int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode); - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - if (!lp.expanded) continue; - - final int width = lp.cellsUsed * cellSize + lp.extraPixels; - child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec); - } - } - - if (heightMode != MeasureSpec.EXACTLY) { - heightSize = maxChildHeight; - } - - setMeasuredDimension(widthSize, heightSize); - //UNUSED mMeasuredExtraWidth = cellsRemaining * cellSize; - } - - /** - * Measure a child view to fit within cell-based formatting. The child's width - * will be measured to a whole multiple of cellSize. - * - *

Sets the expandable and cellsUsed fields of LayoutParams. - * - * @param child Child to measure - * @param cellSize Size of one cell - * @param cellsRemaining Number of cells remaining that this view can expand to fill - * @param parentHeightMeasureSpec MeasureSpec used by the parent view - * @param parentHeightPadding Padding present in the parent view - * @return Number of cells this child was measured to occupy - */ - static int measureChildForCells(View child, int cellSize, int cellsRemaining, - int parentHeightMeasureSpec, int parentHeightPadding) { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) - - parentHeightPadding; - final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); - final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode); - - int cellsUsed = 0; - if (cellsRemaining > 0) { - final int childWidthSpec = MeasureSpec.makeMeasureSpec( - cellSize * cellsRemaining, MeasureSpec.AT_MOST); - child.measure(childWidthSpec, childHeightSpec); - - final int measuredWidth = child.getMeasuredWidth(); - cellsUsed = measuredWidth / cellSize; - if (measuredWidth % cellSize != 0) cellsUsed++; - } - - final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? - (ActionMenuItemView) child : null; - final boolean expandable = !lp.isOverflowButton && itemView != null && itemView.hasText(); - lp.expandable = expandable; - - lp.cellsUsed = cellsUsed; - final int targetWidth = cellsUsed * cellSize; - child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), - childHeightSpec); - return cellsUsed; - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (!mFormatItems) { - super.onLayout(changed, left, top, right, bottom); - return; - } - - final int childCount = getChildCount(); - final int midVertical = (top + bottom) / 2; - final int dividerWidth = 0;//getDividerWidth(); - int overflowWidth = 0; - //UNUSED int nonOverflowWidth = 0; - int nonOverflowCount = 0; - int widthRemaining = right - left - getPaddingRight() - getPaddingLeft(); - boolean hasOverflow = false; - for (int i = 0; i < childCount; i++) { - final View v = getChildAt(i); - if (v.getVisibility() == GONE) { - continue; - } - - LayoutParams p = (LayoutParams) v.getLayoutParams(); - if (p.isOverflowButton) { - overflowWidth = v.getMeasuredWidth(); - if (hasDividerBeforeChildAt(i)) { - overflowWidth += dividerWidth; - } - - int height = v.getMeasuredHeight(); - int r = getWidth() - getPaddingRight() - p.rightMargin; - int l = r - overflowWidth; - int t = midVertical - (height / 2); - int b = t + height; - v.layout(l, t, r, b); - - widthRemaining -= overflowWidth; - hasOverflow = true; - } else { - final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin; - //UNUSED nonOverflowWidth += size; - widthRemaining -= size; - //if (hasDividerBeforeChildAt(i)) { - //UNUSED nonOverflowWidth += dividerWidth; - //} - nonOverflowCount++; - } - } - - if (childCount == 1 && !hasOverflow) { - // Center a single child - final View v = getChildAt(0); - final int width = v.getMeasuredWidth(); - final int height = v.getMeasuredHeight(); - final int midHorizontal = (right - left) / 2; - final int l = midHorizontal - width / 2; - final int t = midVertical - height / 2; - v.layout(l, t, l + width, t + height); - return; - } - - final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1); - final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0); - - int startLeft = getPaddingLeft(); - for (int i = 0; i < childCount; i++) { - final View v = getChildAt(i); - final LayoutParams lp = (LayoutParams) v.getLayoutParams(); - if (v.getVisibility() == GONE || lp.isOverflowButton) { - continue; - } - - startLeft += lp.leftMargin; - int width = v.getMeasuredWidth(); - int height = v.getMeasuredHeight(); - int t = midVertical - height / 2; - v.layout(startLeft, t, startLeft + width, t + height); - startLeft += width + lp.rightMargin + spacerSize; - } - } - - @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mPresenter.dismissPopupMenus(); - } - - public boolean isOverflowReserved() { - return mReserveOverflow; - } - - public void setOverflowReserved(boolean reserveOverflow) { - mReserveOverflow = reserveOverflow; - } - - @Override - protected LayoutParams generateDefaultLayoutParams() { - LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - params.gravity = Gravity.CENTER_VERTICAL; - return params; - } - - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - @Override - protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - if (p instanceof LayoutParams) { - LayoutParams result = new LayoutParams((LayoutParams) p); - if (result.gravity <= Gravity.NO_GRAVITY) { - result.gravity = Gravity.CENTER_VERTICAL; - } - return result; - } - return generateDefaultLayoutParams(); - } - - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p != null && p instanceof LayoutParams; - } - - public LayoutParams generateOverflowButtonLayoutParams() { - LayoutParams result = generateDefaultLayoutParams(); - result.isOverflowButton = true; - return result; - } - - public boolean invokeItem(MenuItemImpl item) { - return mMenu.performItemAction(item, 0); - } - - public int getWindowAnimations() { - return 0; - } - - public void initialize(MenuBuilder menu) { - mMenu = menu; - } - - //@Override - protected boolean hasDividerBeforeChildAt(int childIndex) { - if (childIndex == 0) { - return false; - } - final View childBefore = getChildAt(childIndex - 1); - final View child = getChildAt(childIndex); - boolean result = false; - if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) { - result |= ((ActionMenuChildView) childBefore).needsDividerAfter(); - } - if (childIndex > 0 && child instanceof ActionMenuChildView) { - result |= ((ActionMenuChildView) child).needsDividerBefore(); - } - return result; - } - - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - return false; - } - - public interface ActionMenuChildView { - public boolean needsDividerBefore(); - public boolean needsDividerAfter(); - } - - public static class LayoutParams extends LinearLayout.LayoutParams { - public boolean isOverflowButton; - public int cellsUsed; - public int extraPixels; - public boolean expandable; - public boolean preventEdgeOffset; - - public boolean expanded; - - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - } - - public LayoutParams(LayoutParams other) { - super((LinearLayout.LayoutParams) other); - isOverflowButton = other.isOverflowButton; - } - - public LayoutParams(int width, int height) { - super(width, height); - isOverflowButton = false; - } - - public LayoutParams(int width, int height, boolean isOverflowButton) { - super(width, height); - this.isOverflowButton = isOverflowButton; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java deleted file mode 100644 index 6da26f2ae..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import java.util.ArrayList; -import android.content.Context; -import android.os.Build; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -/** - * Base class for MenuPresenters that have a consistent container view and item - * views. Behaves similarly to an AdapterView in that existing item views will - * be reused if possible when items change. - */ -public abstract class BaseMenuPresenter implements MenuPresenter { - private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; - - protected Context mSystemContext; - protected Context mContext; - protected MenuBuilder mMenu; - protected LayoutInflater mSystemInflater; - protected LayoutInflater mInflater; - private Callback mCallback; - - private int mMenuLayoutRes; - private int mItemLayoutRes; - - protected MenuView mMenuView; - - private int mId; - - /** - * Construct a new BaseMenuPresenter. - * - * @param context Context for generating system-supplied views - * @param menuLayoutRes Layout resource ID for the menu container view - * @param itemLayoutRes Layout resource ID for a single item view - */ - public BaseMenuPresenter(Context context, int menuLayoutRes, int itemLayoutRes) { - mSystemContext = context; - mSystemInflater = LayoutInflater.from(context); - mMenuLayoutRes = menuLayoutRes; - mItemLayoutRes = itemLayoutRes; - } - - @Override - public void initForMenu(Context context, MenuBuilder menu) { - mContext = context; - mInflater = LayoutInflater.from(mContext); - mMenu = menu; - } - - @Override - public MenuView getMenuView(ViewGroup root) { - if (mMenuView == null) { - mMenuView = (MenuView) mSystemInflater.inflate(mMenuLayoutRes, root, false); - mMenuView.initialize(mMenu); - updateMenuView(true); - } - - return mMenuView; - } - - /** - * Reuses item views when it can - */ - public void updateMenuView(boolean cleared) { - final ViewGroup parent = (ViewGroup) mMenuView; - if (parent == null) return; - - int childIndex = 0; - if (mMenu != null) { - mMenu.flagActionItems(); - ArrayList visibleItems = mMenu.getVisibleItems(); - final int itemCount = visibleItems.size(); - for (int i = 0; i < itemCount; i++) { - MenuItemImpl item = visibleItems.get(i); - if (shouldIncludeItem(childIndex, item)) { - final View convertView = parent.getChildAt(childIndex); - final MenuItemImpl oldItem = convertView instanceof MenuView.ItemView ? - ((MenuView.ItemView) convertView).getItemData() : null; - final View itemView = getItemView(item, convertView, parent); - if (item != oldItem) { - // Don't let old states linger with new data. - itemView.setPressed(false); - if (IS_HONEYCOMB) itemView.jumpDrawablesToCurrentState(); - } - if (itemView != convertView) { - addItemView(itemView, childIndex); - } - childIndex++; - } - } - } - - // Remove leftover views. - while (childIndex < parent.getChildCount()) { - if (!filterLeftoverView(parent, childIndex)) { - childIndex++; - } - } - } - - /** - * Add an item view at the given index. - * - * @param itemView View to add - * @param childIndex Index within the parent to insert at - */ - protected void addItemView(View itemView, int childIndex) { - final ViewGroup currentParent = (ViewGroup) itemView.getParent(); - if (currentParent != null) { - currentParent.removeView(itemView); - } - ((ViewGroup) mMenuView).addView(itemView, childIndex); - } - - /** - * Filter the child view at index and remove it if appropriate. - * @param parent Parent to filter from - * @param childIndex Index to filter - * @return true if the child view at index was removed - */ - protected boolean filterLeftoverView(ViewGroup parent, int childIndex) { - parent.removeViewAt(childIndex); - return true; - } - - public void setCallback(Callback cb) { - mCallback = cb; - } - - /** - * Create a new item view that can be re-bound to other item data later. - * - * @return The new item view - */ - public MenuView.ItemView createItemView(ViewGroup parent) { - return (MenuView.ItemView) mSystemInflater.inflate(mItemLayoutRes, parent, false); - } - - /** - * Prepare an item view for use. See AdapterView for the basic idea at work here. - * This may require creating a new item view, but well-behaved implementations will - * re-use the view passed as convertView if present. The returned view will be populated - * with data from the item parameter. - * - * @param item Item to present - * @param convertView Existing view to reuse - * @param parent Intended parent view - use for inflation. - * @return View that presents the requested menu item - */ - public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) { - MenuView.ItemView itemView; - if (convertView instanceof MenuView.ItemView) { - itemView = (MenuView.ItemView) convertView; - } else { - itemView = createItemView(parent); - } - bindItemView(item, itemView); - return (View) itemView; - } - - /** - * Bind item data to an existing item view. - * - * @param item Item to bind - * @param itemView View to populate with item data - */ - public abstract void bindItemView(MenuItemImpl item, MenuView.ItemView itemView); - - /** - * Filter item by child index and item data. - * - * @param childIndex Indended presentation index of this item - * @param item Item to present - * @return true if this item should be included in this menu presentation; false otherwise - */ - public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) { - return true; - } - - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - if (mCallback != null) { - mCallback.onCloseMenu(menu, allMenusAreClosing); - } - } - - public boolean onSubMenuSelected(SubMenuBuilder menu) { - if (mCallback != null) { - return mCallback.onOpenSubMenu(menu); - } - return false; - } - - public boolean flagActionItems() { - return false; - } - - public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { - return false; - } - - public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { - return false; - } - - public int getId() { - return mId; - } - - public void setId(int id) { - mId = id; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java deleted file mode 100644 index ac25c3736..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import com.actionbarsherlock.R; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.RadioButton; -import android.widget.TextView; - -/** - * The item view for each item in the ListView-based MenuViews. - */ -public class ListMenuItemView extends LinearLayout implements MenuView.ItemView { - private MenuItemImpl mItemData; - - private ImageView mIconView; - private RadioButton mRadioButton; - private TextView mTitleView; - private CheckBox mCheckBox; - private TextView mShortcutView; - - private Drawable mBackground; - private int mTextAppearance; - private Context mTextAppearanceContext; - private boolean mPreserveIconSpacing; - - //UNUSED private int mMenuType; - - private LayoutInflater mInflater; - - private boolean mForceShowIcon; - - final Context mContext; - - public ListMenuItemView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs); - mContext = context; - - TypedArray a = - context.obtainStyledAttributes( - attrs, R.styleable.SherlockMenuView, defStyle, 0); - - mBackground = a.getDrawable(R.styleable.SherlockMenuView_itemBackground); - mTextAppearance = a.getResourceId(R.styleable. - SherlockMenuView_itemTextAppearance, -1); - mPreserveIconSpacing = a.getBoolean( - R.styleable.SherlockMenuView_preserveIconSpacing, false); - mTextAppearanceContext = context; - - a.recycle(); - } - - public ListMenuItemView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - setBackgroundDrawable(mBackground); - - mTitleView = (TextView) findViewById(R.id.abs__title); - if (mTextAppearance != -1) { - mTitleView.setTextAppearance(mTextAppearanceContext, - mTextAppearance); - } - - mShortcutView = (TextView) findViewById(R.id.abs__shortcut); - } - - public void initialize(MenuItemImpl itemData, int menuType) { - mItemData = itemData; - //UNUSED mMenuType = menuType; - - setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); - - setTitle(itemData.getTitleForItemView(this)); - setCheckable(itemData.isCheckable()); - setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut()); - setIcon(itemData.getIcon()); - setEnabled(itemData.isEnabled()); - } - - public void setForceShowIcon(boolean forceShow) { - mPreserveIconSpacing = mForceShowIcon = forceShow; - } - - public void setTitle(CharSequence title) { - if (title != null) { - mTitleView.setText(title); - - if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE); - } else { - if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE); - } - } - - public MenuItemImpl getItemData() { - return mItemData; - } - - public void setCheckable(boolean checkable) { - - if (!checkable && mRadioButton == null && mCheckBox == null) { - return; - } - - if (mRadioButton == null) { - insertRadioButton(); - } - if (mCheckBox == null) { - insertCheckBox(); - } - - // Depending on whether its exclusive check or not, the checkbox or - // radio button will be the one in use (and the other will be otherCompoundButton) - final CompoundButton compoundButton; - final CompoundButton otherCompoundButton; - - if (mItemData.isExclusiveCheckable()) { - compoundButton = mRadioButton; - otherCompoundButton = mCheckBox; - } else { - compoundButton = mCheckBox; - otherCompoundButton = mRadioButton; - } - - if (checkable) { - compoundButton.setChecked(mItemData.isChecked()); - - final int newVisibility = checkable ? VISIBLE : GONE; - if (compoundButton.getVisibility() != newVisibility) { - compoundButton.setVisibility(newVisibility); - } - - // Make sure the other compound button isn't visible - if (otherCompoundButton.getVisibility() != GONE) { - otherCompoundButton.setVisibility(GONE); - } - } else { - mCheckBox.setVisibility(GONE); - mRadioButton.setVisibility(GONE); - } - } - - public void setChecked(boolean checked) { - CompoundButton compoundButton; - - if (mItemData.isExclusiveCheckable()) { - if (mRadioButton == null) { - insertRadioButton(); - } - compoundButton = mRadioButton; - } else { - if (mCheckBox == null) { - insertCheckBox(); - } - compoundButton = mCheckBox; - } - - compoundButton.setChecked(checked); - } - - public void setShortcut(boolean showShortcut, char shortcutKey) { - final int newVisibility = (showShortcut && mItemData.shouldShowShortcut()) - ? VISIBLE : GONE; - - if (newVisibility == VISIBLE) { - mShortcutView.setText(mItemData.getShortcutLabel()); - } - - if (mShortcutView.getVisibility() != newVisibility) { - mShortcutView.setVisibility(newVisibility); - } - } - - public void setIcon(Drawable icon) { - final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon; - if (!showIcon && !mPreserveIconSpacing) { - return; - } - - if (mIconView == null && icon == null && !mPreserveIconSpacing) { - return; - } - - if (mIconView == null) { - insertIconView(); - } - - if (icon != null || mPreserveIconSpacing) { - mIconView.setImageDrawable(showIcon ? icon : null); - - if (mIconView.getVisibility() != VISIBLE) { - mIconView.setVisibility(VISIBLE); - } - } else { - mIconView.setVisibility(GONE); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (mIconView != null && mPreserveIconSpacing) { - // Enforce minimum icon spacing - ViewGroup.LayoutParams lp = getLayoutParams(); - LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); - if (lp.height > 0 && iconLp.width <= 0) { - iconLp.width = lp.height; - } - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - private void insertIconView() { - LayoutInflater inflater = getInflater(); - mIconView = (ImageView) inflater.inflate(R.layout.abs__list_menu_item_icon, - this, false); - addView(mIconView, 0); - } - - private void insertRadioButton() { - LayoutInflater inflater = getInflater(); - mRadioButton = - (RadioButton) inflater.inflate(R.layout.abs__list_menu_item_radio, - this, false); - addView(mRadioButton); - } - - private void insertCheckBox() { - LayoutInflater inflater = getInflater(); - mCheckBox = - (CheckBox) inflater.inflate(R.layout.abs__list_menu_item_checkbox, - this, false); - addView(mCheckBox); - } - - public boolean prefersCondensedTitle() { - return false; - } - - public boolean showsIcon() { - return mForceShowIcon; - } - - private LayoutInflater getInflater() { - if (mInflater == null) { - mInflater = LayoutInflater.from(mContext); - } - return mInflater; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java deleted file mode 100644 index 179b8f037..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java +++ /dev/null @@ -1,1335 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Parcelable; -import android.util.SparseArray; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.View; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -/** - * Implementation of the {@link android.view.Menu} interface for creating a - * standard menu UI. - */ -public class MenuBuilder implements Menu { - //UNUSED private static final String TAG = "MenuBuilder"; - - private static final String PRESENTER_KEY = "android:menu:presenters"; - private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates"; - private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview"; - - private static final int[] sCategoryToOrder = new int[] { - 1, /* No category */ - 4, /* CONTAINER */ - 5, /* SYSTEM */ - 3, /* SECONDARY */ - 2, /* ALTERNATIVE */ - 0, /* SELECTED_ALTERNATIVE */ - }; - - private final Context mContext; - private final Resources mResources; - - /** - * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() - * instead of accessing this directly. - */ - private boolean mQwertyMode; - - /** - * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() - * instead of accessing this directly. - */ - private boolean mShortcutsVisible; - - /** - * Callback that will receive the various menu-related events generated by - * this class. Use getCallback to get a reference to the callback. - */ - private Callback mCallback; - - /** Contains all of the items for this menu */ - private ArrayList mItems; - - /** Contains only the items that are currently visible. This will be created/refreshed from - * {@link #getVisibleItems()} */ - private ArrayList mVisibleItems; - /** - * Whether or not the items (or any one item's shown state) has changed since it was last - * fetched from {@link #getVisibleItems()} - */ - private boolean mIsVisibleItemsStale; - - /** - * Contains only the items that should appear in the Action Bar, if present. - */ - private ArrayList mActionItems; - /** - * Contains items that should NOT appear in the Action Bar, if present. - */ - private ArrayList mNonActionItems; - - /** - * Whether or not the items (or any one item's action state) has changed since it was - * last fetched. - */ - private boolean mIsActionItemsStale; - - /** - * Default value for how added items should show in the action list. - */ - private int mDefaultShowAsAction = MenuItem.SHOW_AS_ACTION_NEVER; - - /** - * Current use case is Context Menus: As Views populate the context menu, each one has - * extra information that should be passed along. This is the current menu info that - * should be set on all items added to this menu. - */ - private ContextMenuInfo mCurrentMenuInfo; - - /** Header title for menu types that have a header (context and submenus) */ - CharSequence mHeaderTitle; - /** Header icon for menu types that have a header and support icons (context) */ - Drawable mHeaderIcon; - /** Header custom view for menu types that have a header and support custom views (context) */ - View mHeaderView; - - /** - * Contains the state of the View hierarchy for all menu views when the menu - * was frozen. - */ - //UNUSED private SparseArray mFrozenViewStates; - - /** - * Prevents onItemsChanged from doing its junk, useful for batching commands - * that may individually call onItemsChanged. - */ - private boolean mPreventDispatchingItemsChanged = false; - private boolean mItemsChangedWhileDispatchPrevented = false; - - private boolean mOptionalIconsVisible = false; - - private boolean mIsClosing = false; - - private ArrayList mTempShortcutItemList = new ArrayList(); - - private CopyOnWriteArrayList> mPresenters = - new CopyOnWriteArrayList>(); - - /** - * Currently expanded menu item; must be collapsed when we clear. - */ - private MenuItemImpl mExpandedItem; - - /** - * Called by menu to notify of close and selection changes. - */ - public interface Callback { - /** - * Called when a menu item is selected. - * @param menu The menu that is the parent of the item - * @param item The menu item that is selected - * @return whether the menu item selection was handled - */ - public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item); - - /** - * Called when the mode of the menu changes (for example, from icon to expanded). - * - * @param menu the menu that has changed modes - */ - public void onMenuModeChange(MenuBuilder menu); - } - - /** - * Called by menu items to execute their associated action - */ - public interface ItemInvoker { - public boolean invokeItem(MenuItemImpl item); - } - - public MenuBuilder(Context context) { - mContext = context; - mResources = context.getResources(); - - mItems = new ArrayList(); - - mVisibleItems = new ArrayList(); - mIsVisibleItemsStale = true; - - mActionItems = new ArrayList(); - mNonActionItems = new ArrayList(); - mIsActionItemsStale = true; - - setShortcutsVisibleInner(true); - } - - public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) { - mDefaultShowAsAction = defaultShowAsAction; - return this; - } - - /** - * Add a presenter to this menu. This will only hold a WeakReference; - * you do not need to explicitly remove a presenter, but you can using - * {@link #removeMenuPresenter(MenuPresenter)}. - * - * @param presenter The presenter to add - */ - public void addMenuPresenter(MenuPresenter presenter) { - mPresenters.add(new WeakReference(presenter)); - presenter.initForMenu(mContext, this); - mIsActionItemsStale = true; - } - - /** - * Remove a presenter from this menu. That presenter will no longer - * receive notifications of updates to this menu's data. - * - * @param presenter The presenter to remove - */ - public void removeMenuPresenter(MenuPresenter presenter) { - for (WeakReference ref : mPresenters) { - final MenuPresenter item = ref.get(); - if (item == null || item == presenter) { - mPresenters.remove(ref); - } - } - } - - private void dispatchPresenterUpdate(boolean cleared) { - if (mPresenters.isEmpty()) return; - - stopDispatchingItemsChanged(); - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else { - presenter.updateMenuView(cleared); - } - } - startDispatchingItemsChanged(); - } - - private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) { - if (mPresenters.isEmpty()) return false; - - boolean result = false; - - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else if (!result) { - result = presenter.onSubMenuSelected(subMenu); - } - } - return result; - } - - private void dispatchSaveInstanceState(Bundle outState) { - if (mPresenters.isEmpty()) return; - - SparseArray presenterStates = new SparseArray(); - - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else { - final int id = presenter.getId(); - if (id > 0) { - final Parcelable state = presenter.onSaveInstanceState(); - if (state != null) { - presenterStates.put(id, state); - } - } - } - } - - outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates); - } - - private void dispatchRestoreInstanceState(Bundle state) { - SparseArray presenterStates = state.getSparseParcelableArray(PRESENTER_KEY); - - if (presenterStates == null || mPresenters.isEmpty()) return; - - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else { - final int id = presenter.getId(); - if (id > 0) { - Parcelable parcel = presenterStates.get(id); - if (parcel != null) { - presenter.onRestoreInstanceState(parcel); - } - } - } - } - } - - public void savePresenterStates(Bundle outState) { - dispatchSaveInstanceState(outState); - } - - public void restorePresenterStates(Bundle state) { - dispatchRestoreInstanceState(state); - } - - public void saveActionViewStates(Bundle outStates) { - SparseArray viewStates = null; - - final int itemCount = size(); - for (int i = 0; i < itemCount; i++) { - final MenuItem item = getItem(i); - final View v = item.getActionView(); - if (v != null && v.getId() != View.NO_ID) { - if (viewStates == null) { - viewStates = new SparseArray(); - } - v.saveHierarchyState(viewStates); - if (item.isActionViewExpanded()) { - outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId()); - } - } - if (item.hasSubMenu()) { - final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); - subMenu.saveActionViewStates(outStates); - } - } - - if (viewStates != null) { - outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates); - } - } - - public void restoreActionViewStates(Bundle states) { - if (states == null) { - return; - } - - SparseArray viewStates = states.getSparseParcelableArray( - getActionViewStatesKey()); - - final int itemCount = size(); - for (int i = 0; i < itemCount; i++) { - final MenuItem item = getItem(i); - final View v = item.getActionView(); - if (v != null && v.getId() != View.NO_ID) { - v.restoreHierarchyState(viewStates); - } - if (item.hasSubMenu()) { - final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); - subMenu.restoreActionViewStates(states); - } - } - - final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID); - if (expandedId > 0) { - MenuItem itemToExpand = findItem(expandedId); - if (itemToExpand != null) { - itemToExpand.expandActionView(); - } - } - } - - protected String getActionViewStatesKey() { - return ACTION_VIEW_STATES_KEY; - } - - public void setCallback(Callback cb) { - mCallback = cb; - } - - /** - * Adds an item to the menu. The other add methods funnel to this. - */ - private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) { - final int ordering = getOrdering(categoryOrder); - - final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, - ordering, title, mDefaultShowAsAction); - - if (mCurrentMenuInfo != null) { - // Pass along the current menu info - item.setMenuInfo(mCurrentMenuInfo); - } - - mItems.add(findInsertIndex(mItems, ordering), item); - onItemsChanged(true); - - return item; - } - - public MenuItem add(CharSequence title) { - return addInternal(0, 0, 0, title); - } - - public MenuItem add(int titleRes) { - return addInternal(0, 0, 0, mResources.getString(titleRes)); - } - - public MenuItem add(int group, int id, int categoryOrder, CharSequence title) { - return addInternal(group, id, categoryOrder, title); - } - - public MenuItem add(int group, int id, int categoryOrder, int title) { - return addInternal(group, id, categoryOrder, mResources.getString(title)); - } - - public SubMenu addSubMenu(CharSequence title) { - return addSubMenu(0, 0, 0, title); - } - - public SubMenu addSubMenu(int titleRes) { - return addSubMenu(0, 0, 0, mResources.getString(titleRes)); - } - - public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) { - final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title); - final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item); - item.setSubMenu(subMenu); - - return subMenu; - } - - public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) { - return addSubMenu(group, id, categoryOrder, mResources.getString(title)); - } - - public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller, - Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { - PackageManager pm = mContext.getPackageManager(); - final List lri = - pm.queryIntentActivityOptions(caller, specifics, intent, 0); - final int N = lri != null ? lri.size() : 0; - - if ((flags & FLAG_APPEND_TO_GROUP) == 0) { - removeGroup(group); - } - - for (int i=0; i= 0) { - outSpecificItems[ri.specificIndex] = item; - } - } - - return N; - } - - public void removeItem(int id) { - removeItemAtInt(findItemIndex(id), true); - } - - public void removeGroup(int group) { - final int i = findGroupIndex(group); - - if (i >= 0) { - final int maxRemovable = mItems.size() - i; - int numRemoved = 0; - while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) { - // Don't force update for each one, this method will do it at the end - removeItemAtInt(i, false); - } - - // Notify menu views - onItemsChanged(true); - } - } - - /** - * Remove the item at the given index and optionally forces menu views to - * update. - * - * @param index The index of the item to be removed. If this index is - * invalid an exception is thrown. - * @param updateChildrenOnMenuViews Whether to force update on menu views. - * Please make sure you eventually call this after your batch of - * removals. - */ - private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) { - if ((index < 0) || (index >= mItems.size())) return; - - mItems.remove(index); - - if (updateChildrenOnMenuViews) onItemsChanged(true); - } - - public void removeItemAt(int index) { - removeItemAtInt(index, true); - } - - public void clearAll() { - mPreventDispatchingItemsChanged = true; - clear(); - clearHeader(); - mPreventDispatchingItemsChanged = false; - mItemsChangedWhileDispatchPrevented = false; - onItemsChanged(true); - } - - public void clear() { - if (mExpandedItem != null) { - collapseItemActionView(mExpandedItem); - } - mItems.clear(); - - onItemsChanged(true); - } - - void setExclusiveItemChecked(MenuItem item) { - final int group = item.getGroupId(); - - final int N = mItems.size(); - for (int i = 0; i < N; i++) { - MenuItemImpl curItem = mItems.get(i); - if (curItem.getGroupId() == group) { - if (!curItem.isExclusiveCheckable()) continue; - if (!curItem.isCheckable()) continue; - - // Check the item meant to be checked, uncheck the others (that are in the group) - curItem.setCheckedInt(curItem == item); - } - } - } - - public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { - final int N = mItems.size(); - - for (int i = 0; i < N; i++) { - MenuItemImpl item = mItems.get(i); - if (item.getGroupId() == group) { - item.setExclusiveCheckable(exclusive); - item.setCheckable(checkable); - } - } - } - - public void setGroupVisible(int group, boolean visible) { - final int N = mItems.size(); - - // We handle the notification of items being changed ourselves, so we use setVisibleInt rather - // than setVisible and at the end notify of items being changed - - boolean changedAtLeastOneItem = false; - for (int i = 0; i < N; i++) { - MenuItemImpl item = mItems.get(i); - if (item.getGroupId() == group) { - if (item.setVisibleInt(visible)) changedAtLeastOneItem = true; - } - } - - if (changedAtLeastOneItem) onItemsChanged(true); - } - - public void setGroupEnabled(int group, boolean enabled) { - final int N = mItems.size(); - - for (int i = 0; i < N; i++) { - MenuItemImpl item = mItems.get(i); - if (item.getGroupId() == group) { - item.setEnabled(enabled); - } - } - } - - public boolean hasVisibleItems() { - final int size = size(); - - for (int i = 0; i < size; i++) { - MenuItemImpl item = mItems.get(i); - if (item.isVisible()) { - return true; - } - } - - return false; - } - - public MenuItem findItem(int id) { - final int size = size(); - for (int i = 0; i < size; i++) { - MenuItemImpl item = mItems.get(i); - if (item.getItemId() == id) { - return item; - } else if (item.hasSubMenu()) { - MenuItem possibleItem = item.getSubMenu().findItem(id); - - if (possibleItem != null) { - return possibleItem; - } - } - } - - return null; - } - - public int findItemIndex(int id) { - final int size = size(); - - for (int i = 0; i < size; i++) { - MenuItemImpl item = mItems.get(i); - if (item.getItemId() == id) { - return i; - } - } - - return -1; - } - - public int findGroupIndex(int group) { - return findGroupIndex(group, 0); - } - - public int findGroupIndex(int group, int start) { - final int size = size(); - - if (start < 0) { - start = 0; - } - - for (int i = start; i < size; i++) { - final MenuItemImpl item = mItems.get(i); - - if (item.getGroupId() == group) { - return i; - } - } - - return -1; - } - - public int size() { - return mItems.size(); - } - - /** {@inheritDoc} */ - public MenuItem getItem(int index) { - return mItems.get(index); - } - - public boolean isShortcutKey(int keyCode, KeyEvent event) { - return findItemWithShortcutForKey(keyCode, event) != null; - } - - public void setQwertyMode(boolean isQwerty) { - mQwertyMode = isQwerty; - - onItemsChanged(false); - } - - /** - * Returns the ordering across all items. This will grab the category from - * the upper bits, find out how to order the category with respect to other - * categories, and combine it with the lower bits. - * - * @param categoryOrder The category order for a particular item (if it has - * not been or/add with a category, the default category is - * assumed). - * @return An ordering integer that can be used to order this item across - * all the items (even from other categories). - */ - private static int getOrdering(int categoryOrder) { - final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT; - - if (index < 0 || index >= sCategoryToOrder.length) { - throw new IllegalArgumentException("order does not contain a valid category."); - } - - return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK); - } - - /** - * @return whether the menu shortcuts are in qwerty mode or not - */ - boolean isQwertyMode() { - return mQwertyMode; - } - - /** - * Sets whether the shortcuts should be visible on menus. Devices without hardware - * key input will never make shortcuts visible even if this method is passed 'true'. - * - * @param shortcutsVisible Whether shortcuts should be visible (if true and a - * menu item does not have a shortcut defined, that item will - * still NOT show a shortcut) - */ - public void setShortcutsVisible(boolean shortcutsVisible) { - if (mShortcutsVisible == shortcutsVisible) return; - - setShortcutsVisibleInner(shortcutsVisible); - onItemsChanged(false); - } - - private void setShortcutsVisibleInner(boolean shortcutsVisible) { - mShortcutsVisible = shortcutsVisible - && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS - && mResources.getBoolean( - R.bool.abs__config_showMenuShortcutsWhenKeyboardPresent); - } - - /** - * @return Whether shortcuts should be visible on menus. - */ - public boolean isShortcutsVisible() { - return mShortcutsVisible; - } - - Resources getResources() { - return mResources; - } - - public Context getContext() { - return mContext; - } - - boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) { - return mCallback != null && mCallback.onMenuItemSelected(menu, item); - } - - /** - * Dispatch a mode change event to this menu's callback. - */ - public void changeMenuMode() { - if (mCallback != null) { - mCallback.onMenuModeChange(this); - } - } - - private static int findInsertIndex(ArrayList items, int ordering) { - for (int i = items.size() - 1; i >= 0; i--) { - MenuItemImpl item = items.get(i); - if (item.getOrdering() <= ordering) { - return i + 1; - } - } - - return 0; - } - - public boolean performShortcut(int keyCode, KeyEvent event, int flags) { - final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event); - - boolean handled = false; - - if (item != null) { - handled = performItemAction(item, flags); - } - - if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) { - close(true); - } - - return handled; - } - - /* - * This function will return all the menu and sub-menu items that can - * be directly (the shortcut directly corresponds) and indirectly - * (the ALT-enabled char corresponds to the shortcut) associated - * with the keyCode. - */ - @SuppressWarnings("deprecation") - void findItemsWithShortcutForKey(List items, int keyCode, KeyEvent event) { - final boolean qwerty = isQwertyMode(); - final int metaState = event.getMetaState(); - final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); - // Get the chars associated with the keyCode (i.e using any chording combo) - final boolean isKeyCodeMapped = event.getKeyData(possibleChars); - // The delete key is not mapped to '\b' so we treat it specially - if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) { - return; - } - - // Look for an item whose shortcut is this key. - final int N = mItems.size(); - for (int i = 0; i < N; i++) { - MenuItemImpl item = mItems.get(i); - if (item.hasSubMenu()) { - ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event); - } - final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); - if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) && - (shortcutChar != 0) && - (shortcutChar == possibleChars.meta[0] - || shortcutChar == possibleChars.meta[2] - || (qwerty && shortcutChar == '\b' && - keyCode == KeyEvent.KEYCODE_DEL)) && - item.isEnabled()) { - items.add(item); - } - } - } - - /* - * We want to return the menu item associated with the key, but if there is no - * ambiguity (i.e. there is only one menu item corresponding to the key) we want - * to return it even if it's not an exact match; this allow the user to - * _not_ use the ALT key for example, making the use of shortcuts slightly more - * user-friendly. An example is on the G1, '!' and '1' are on the same key, and - * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut). - * - * On the other hand, if two (or more) shortcuts corresponds to the same key, - * we have to only return the exact match. - */ - @SuppressWarnings("deprecation") - MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) { - // Get all items that can be associated directly or indirectly with the keyCode - ArrayList items = mTempShortcutItemList; - items.clear(); - findItemsWithShortcutForKey(items, keyCode, event); - - if (items.isEmpty()) { - return null; - } - - final int metaState = event.getMetaState(); - final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); - // Get the chars associated with the keyCode (i.e using any chording combo) - event.getKeyData(possibleChars); - - // If we have only one element, we can safely returns it - final int size = items.size(); - if (size == 1) { - return items.get(0); - } - - final boolean qwerty = isQwertyMode(); - // If we found more than one item associated with the key, - // we have to return the exact match - for (int i = 0; i < size; i++) { - final MenuItemImpl item = items.get(i); - final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : - item.getNumericShortcut(); - if ((shortcutChar == possibleChars.meta[0] && - (metaState & KeyEvent.META_ALT_ON) == 0) - || (shortcutChar == possibleChars.meta[2] && - (metaState & KeyEvent.META_ALT_ON) != 0) - || (qwerty && shortcutChar == '\b' && - keyCode == KeyEvent.KEYCODE_DEL)) { - return item; - } - } - return null; - } - - public boolean performIdentifierAction(int id, int flags) { - // Look for an item whose identifier is the id. - return performItemAction(findItem(id), flags); - } - - public boolean performItemAction(MenuItem item, int flags) { - MenuItemImpl itemImpl = (MenuItemImpl) item; - - if (itemImpl == null || !itemImpl.isEnabled()) { - return false; - } - - boolean invoked = itemImpl.invoke(); - - if (itemImpl.hasCollapsibleActionView()) { - invoked |= itemImpl.expandActionView(); - if (invoked) close(true); - } else if (item.hasSubMenu()) { - close(false); - - final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); - final ActionProvider provider = item.getActionProvider(); - if (provider != null && provider.hasSubMenu()) { - provider.onPrepareSubMenu(subMenu); - } - invoked |= dispatchSubMenuSelected(subMenu); - if (!invoked) close(true); - } else { - if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) { - close(true); - } - } - - return invoked; - } - - /** - * Closes the visible menu. - * - * @param allMenusAreClosing Whether the menus are completely closing (true), - * or whether there is another menu coming in this menu's place - * (false). For example, if the menu is closing because a - * sub menu is about to be shown, allMenusAreClosing - * is false. - */ - final void close(boolean allMenusAreClosing) { - if (mIsClosing) return; - - mIsClosing = true; - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else { - presenter.onCloseMenu(this, allMenusAreClosing); - } - } - mIsClosing = false; - } - - /** {@inheritDoc} */ - public void close() { - close(true); - } - - /** - * Called when an item is added or removed. - * - * @param structureChanged true if the menu structure changed, - * false if only item properties changed. - * (Visibility is a structural property since it affects layout.) - */ - void onItemsChanged(boolean structureChanged) { - if (!mPreventDispatchingItemsChanged) { - if (structureChanged) { - mIsVisibleItemsStale = true; - mIsActionItemsStale = true; - } - - dispatchPresenterUpdate(structureChanged); - } else { - mItemsChangedWhileDispatchPrevented = true; - } - } - - /** - * Stop dispatching item changed events to presenters until - * {@link #startDispatchingItemsChanged()} is called. Useful when - * many menu operations are going to be performed as a batch. - */ - public void stopDispatchingItemsChanged() { - if (!mPreventDispatchingItemsChanged) { - mPreventDispatchingItemsChanged = true; - mItemsChangedWhileDispatchPrevented = false; - } - } - - public void startDispatchingItemsChanged() { - mPreventDispatchingItemsChanged = false; - - if (mItemsChangedWhileDispatchPrevented) { - mItemsChangedWhileDispatchPrevented = false; - onItemsChanged(true); - } - } - - /** - * Called by {@link MenuItemImpl} when its visible flag is changed. - * @param item The item that has gone through a visibility change. - */ - void onItemVisibleChanged(MenuItemImpl item) { - // Notify of items being changed - mIsVisibleItemsStale = true; - onItemsChanged(true); - } - - /** - * Called by {@link MenuItemImpl} when its action request status is changed. - * @param item The item that has gone through a change in action request status. - */ - void onItemActionRequestChanged(MenuItemImpl item) { - // Notify of items being changed - mIsActionItemsStale = true; - onItemsChanged(true); - } - - ArrayList getVisibleItems() { - if (!mIsVisibleItemsStale) return mVisibleItems; - - // Refresh the visible items - mVisibleItems.clear(); - - final int itemsSize = mItems.size(); - MenuItemImpl item; - for (int i = 0; i < itemsSize; i++) { - item = mItems.get(i); - if (item.isVisible()) mVisibleItems.add(item); - } - - mIsVisibleItemsStale = false; - mIsActionItemsStale = true; - - return mVisibleItems; - } - - /** - * This method determines which menu items get to be 'action items' that will appear - * in an action bar and which items should be 'overflow items' in a secondary menu. - * The rules are as follows: - * - *

Items are considered for inclusion in the order specified within the menu. - * There is a limit of mMaxActionItems as a total count, optionally including the overflow - * menu button itself. This is a soft limit; if an item shares a group ID with an item - * previously included as an action item, the new item will stay with its group and become - * an action item itself even if it breaks the max item count limit. This is done to - * limit the conceptual complexity of the items presented within an action bar. Only a few - * unrelated concepts should be presented to the user in this space, and groups are treated - * as a single concept. - * - *

There is also a hard limit of consumed measurable space: mActionWidthLimit. This - * limit may be broken by a single item that exceeds the remaining space, but no further - * items may be added. If an item that is part of a group cannot fit within the remaining - * measured width, the entire group will be demoted to overflow. This is done to ensure room - * for navigation and other affordances in the action bar as well as reduce general UI clutter. - * - *

The space freed by demoting a full group cannot be consumed by future menu items. - * Once items begin to overflow, all future items become overflow items as well. This is - * to avoid inadvertent reordering that may break the app's intended design. - */ - public void flagActionItems() { - if (!mIsActionItemsStale) { - return; - } - - // Presenters flag action items as needed. - boolean flagged = false; - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else { - flagged |= presenter.flagActionItems(); - } - } - - if (flagged) { - mActionItems.clear(); - mNonActionItems.clear(); - ArrayList visibleItems = getVisibleItems(); - final int itemsSize = visibleItems.size(); - for (int i = 0; i < itemsSize; i++) { - MenuItemImpl item = visibleItems.get(i); - if (item.isActionButton()) { - mActionItems.add(item); - } else { - mNonActionItems.add(item); - } - } - } else { - // Nobody flagged anything, everything is a non-action item. - // (This happens during a first pass with no action-item presenters.) - mActionItems.clear(); - mNonActionItems.clear(); - mNonActionItems.addAll(getVisibleItems()); - } - mIsActionItemsStale = false; - } - - ArrayList getActionItems() { - flagActionItems(); - return mActionItems; - } - - ArrayList getNonActionItems() { - flagActionItems(); - return mNonActionItems; - } - - public void clearHeader() { - mHeaderIcon = null; - mHeaderTitle = null; - mHeaderView = null; - - onItemsChanged(false); - } - - private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes, - final Drawable icon, final View view) { - final Resources r = getResources(); - - if (view != null) { - mHeaderView = view; - - // If using a custom view, then the title and icon aren't used - mHeaderTitle = null; - mHeaderIcon = null; - } else { - if (titleRes > 0) { - mHeaderTitle = r.getText(titleRes); - } else if (title != null) { - mHeaderTitle = title; - } - - if (iconRes > 0) { - mHeaderIcon = r.getDrawable(iconRes); - } else if (icon != null) { - mHeaderIcon = icon; - } - - // If using the title or icon, then a custom view isn't used - mHeaderView = null; - } - - // Notify of change - onItemsChanged(false); - } - - /** - * Sets the header's title. This replaces the header view. Called by the - * builder-style methods of subclasses. - * - * @param title The new title. - * @return This MenuBuilder so additional setters can be called. - */ - protected MenuBuilder setHeaderTitleInt(CharSequence title) { - setHeaderInternal(0, title, 0, null, null); - return this; - } - - /** - * Sets the header's title. This replaces the header view. Called by the - * builder-style methods of subclasses. - * - * @param titleRes The new title (as a resource ID). - * @return This MenuBuilder so additional setters can be called. - */ - protected MenuBuilder setHeaderTitleInt(int titleRes) { - setHeaderInternal(titleRes, null, 0, null, null); - return this; - } - - /** - * Sets the header's icon. This replaces the header view. Called by the - * builder-style methods of subclasses. - * - * @param icon The new icon. - * @return This MenuBuilder so additional setters can be called. - */ - protected MenuBuilder setHeaderIconInt(Drawable icon) { - setHeaderInternal(0, null, 0, icon, null); - return this; - } - - /** - * Sets the header's icon. This replaces the header view. Called by the - * builder-style methods of subclasses. - * - * @param iconRes The new icon (as a resource ID). - * @return This MenuBuilder so additional setters can be called. - */ - protected MenuBuilder setHeaderIconInt(int iconRes) { - setHeaderInternal(0, null, iconRes, null, null); - return this; - } - - /** - * Sets the header's view. This replaces the title and icon. Called by the - * builder-style methods of subclasses. - * - * @param view The new view. - * @return This MenuBuilder so additional setters can be called. - */ - protected MenuBuilder setHeaderViewInt(View view) { - setHeaderInternal(0, null, 0, null, view); - return this; - } - - public CharSequence getHeaderTitle() { - return mHeaderTitle; - } - - public Drawable getHeaderIcon() { - return mHeaderIcon; - } - - public View getHeaderView() { - return mHeaderView; - } - - /** - * Gets the root menu (if this is a submenu, find its root menu). - * @return The root menu. - */ - public MenuBuilder getRootMenu() { - return this; - } - - /** - * Sets the current menu info that is set on all items added to this menu - * (until this is called again with different menu info, in which case that - * one will be added to all subsequent item additions). - * - * @param menuInfo The extra menu information to add. - */ - public void setCurrentMenuInfo(ContextMenuInfo menuInfo) { - mCurrentMenuInfo = menuInfo; - } - - void setOptionalIconsVisible(boolean visible) { - mOptionalIconsVisible = visible; - } - - boolean getOptionalIconsVisible() { - return mOptionalIconsVisible; - } - - public boolean expandItemActionView(MenuItemImpl item) { - if (mPresenters.isEmpty()) return false; - - boolean expanded = false; - - stopDispatchingItemsChanged(); - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else if ((expanded = presenter.expandItemActionView(this, item))) { - break; - } - } - startDispatchingItemsChanged(); - - if (expanded) { - mExpandedItem = item; - } - return expanded; - } - - public boolean collapseItemActionView(MenuItemImpl item) { - if (mPresenters.isEmpty() || mExpandedItem != item) return false; - - boolean collapsed = false; - - stopDispatchingItemsChanged(); - for (WeakReference ref : mPresenters) { - final MenuPresenter presenter = ref.get(); - if (presenter == null) { - mPresenters.remove(ref); - } else if ((collapsed = presenter.collapseItemActionView(this, item))) { - break; - } - } - startDispatchingItemsChanged(); - - if (collapsed) { - mExpandedItem = null; - } - return collapsed; - } - - public MenuItemImpl getExpandedItem() { - return mExpandedItem; - } - - public boolean bindNativeOverflow(android.view.Menu menu, android.view.MenuItem.OnMenuItemClickListener listener, HashMap map) { - final List nonActionItems = getNonActionItems(); - if (nonActionItems == null || nonActionItems.size() == 0) { - return false; - } - - boolean visible = false; - menu.clear(); - for (MenuItemImpl nonActionItem : nonActionItems) { - if (!nonActionItem.isVisible()) { - continue; - } - visible = true; - - android.view.MenuItem nativeItem; - if (nonActionItem.hasSubMenu()) { - android.view.SubMenu nativeSub = menu.addSubMenu(nonActionItem.getGroupId(), nonActionItem.getItemId(), - nonActionItem.getOrder(), nonActionItem.getTitle()); - - SubMenuBuilder subMenu = (SubMenuBuilder)nonActionItem.getSubMenu(); - for (MenuItemImpl subItem : subMenu.getVisibleItems()) { - android.view.MenuItem nativeSubItem = nativeSub.add(subItem.getGroupId(), subItem.getItemId(), - subItem.getOrder(), subItem.getTitle()); - - nativeSubItem.setIcon(subItem.getIcon()); - nativeSubItem.setOnMenuItemClickListener(listener); - nativeSubItem.setEnabled(subItem.isEnabled()); - nativeSubItem.setIntent(subItem.getIntent()); - nativeSubItem.setNumericShortcut(subItem.getNumericShortcut()); - nativeSubItem.setAlphabeticShortcut(subItem.getAlphabeticShortcut()); - nativeSubItem.setTitleCondensed(subItem.getTitleCondensed()); - nativeSubItem.setCheckable(subItem.isCheckable()); - nativeSubItem.setChecked(subItem.isChecked()); - - if (subItem.isExclusiveCheckable()) { - nativeSub.setGroupCheckable(subItem.getGroupId(), true, true); - } - - map.put(nativeSubItem, subItem); - } - - nativeItem = nativeSub.getItem(); - } else { - nativeItem = menu.add(nonActionItem.getGroupId(), nonActionItem.getItemId(), - nonActionItem.getOrder(), nonActionItem.getTitle()); - } - nativeItem.setIcon(nonActionItem.getIcon()); - nativeItem.setOnMenuItemClickListener(listener); - nativeItem.setEnabled(nonActionItem.isEnabled()); - nativeItem.setIntent(nonActionItem.getIntent()); - nativeItem.setNumericShortcut(nonActionItem.getNumericShortcut()); - nativeItem.setAlphabeticShortcut(nonActionItem.getAlphabeticShortcut()); - nativeItem.setTitleCondensed(nonActionItem.getTitleCondensed()); - nativeItem.setCheckable(nonActionItem.isCheckable()); - nativeItem.setChecked(nonActionItem.isChecked()); - - if (nonActionItem.isExclusiveCheckable()) { - menu.setGroupCheckable(nonActionItem.getGroupId(), true, true); - } - - map.put(nativeItem, nonActionItem); - } - return visible; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java deleted file mode 100644 index f5359fb40..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java +++ /dev/null @@ -1,647 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.util.Log; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewDebug; -import android.widget.LinearLayout; - -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -/** - * @hide - */ -public final class MenuItemImpl implements MenuItem { - private static final String TAG = "MenuItemImpl"; - - private static final int SHOW_AS_ACTION_MASK = SHOW_AS_ACTION_NEVER | - SHOW_AS_ACTION_IF_ROOM | - SHOW_AS_ACTION_ALWAYS; - - private final int mId; - private final int mGroup; - private final int mCategoryOrder; - private final int mOrdering; - private CharSequence mTitle; - private CharSequence mTitleCondensed; - private Intent mIntent; - private char mShortcutNumericChar; - private char mShortcutAlphabeticChar; - - /** The icon's drawable which is only created as needed */ - private Drawable mIconDrawable; - /** - * The icon's resource ID which is used to get the Drawable when it is - * needed (if the Drawable isn't already obtained--only one of the two is - * needed). - */ - private int mIconResId = NO_ICON; - - /** The menu to which this item belongs */ - private MenuBuilder mMenu; - /** If this item should launch a sub menu, this is the sub menu to launch */ - private SubMenuBuilder mSubMenu; - - private Runnable mItemCallback; - private MenuItem.OnMenuItemClickListener mClickListener; - - private int mFlags = ENABLED; - private static final int CHECKABLE = 0x00000001; - private static final int CHECKED = 0x00000002; - private static final int EXCLUSIVE = 0x00000004; - private static final int HIDDEN = 0x00000008; - private static final int ENABLED = 0x00000010; - private static final int IS_ACTION = 0x00000020; - - private int mShowAsAction = SHOW_AS_ACTION_NEVER; - - private View mActionView; - private ActionProvider mActionProvider; - private OnActionExpandListener mOnActionExpandListener; - private boolean mIsActionViewExpanded = false; - - /** Used for the icon resource ID if this item does not have an icon */ - static final int NO_ICON = 0; - - /** - * Current use case is for context menu: Extra information linked to the - * View that added this item to the context menu. - */ - private ContextMenuInfo mMenuInfo; - - private static String sPrependShortcutLabel; - private static String sEnterShortcutLabel; - private static String sDeleteShortcutLabel; - private static String sSpaceShortcutLabel; - - - /** - * Instantiates this menu item. - * - * @param menu - * @param group Item ordering grouping control. The item will be added after - * all other items whose order is <= this number, and before any - * that are larger than it. This can also be used to define - * groups of items for batch state changes. Normally use 0. - * @param id Unique item ID. Use 0 if you do not need a unique ID. - * @param categoryOrder The ordering for this item. - * @param title The text to display for the item. - */ - MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering, - CharSequence title, int showAsAction) { - - /* TODO if (sPrependShortcutLabel == null) { - // This is instantiated from the UI thread, so no chance of sync issues - sPrependShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.prepend_shortcut_label); - sEnterShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.menu_enter_shortcut_label); - sDeleteShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.menu_delete_shortcut_label); - sSpaceShortcutLabel = menu.getContext().getResources().getString( - com.android.internal.R.string.menu_space_shortcut_label); - }*/ - - mMenu = menu; - mId = id; - mGroup = group; - mCategoryOrder = categoryOrder; - mOrdering = ordering; - mTitle = title; - mShowAsAction = showAsAction; - } - - /** - * Invokes the item by calling various listeners or callbacks. - * - * @return true if the invocation was handled, false otherwise - */ - public boolean invoke() { - if (mClickListener != null && - mClickListener.onMenuItemClick(this)) { - return true; - } - - if (mMenu.dispatchMenuItemSelected(mMenu.getRootMenu(), this)) { - return true; - } - - if (mItemCallback != null) { - mItemCallback.run(); - return true; - } - - if (mIntent != null) { - try { - mMenu.getContext().startActivity(mIntent); - return true; - } catch (ActivityNotFoundException e) { - Log.e(TAG, "Can't find activity to handle intent; ignoring", e); - } - } - - if (mActionProvider != null && mActionProvider.onPerformDefaultAction()) { - return true; - } - - return false; - } - - public boolean isEnabled() { - return (mFlags & ENABLED) != 0; - } - - public MenuItem setEnabled(boolean enabled) { - if (enabled) { - mFlags |= ENABLED; - } else { - mFlags &= ~ENABLED; - } - - mMenu.onItemsChanged(false); - - return this; - } - - public int getGroupId() { - return mGroup; - } - - @ViewDebug.CapturedViewProperty - public int getItemId() { - return mId; - } - - public int getOrder() { - return mCategoryOrder; - } - - public int getOrdering() { - return mOrdering; - } - - public Intent getIntent() { - return mIntent; - } - - public MenuItem setIntent(Intent intent) { - mIntent = intent; - return this; - } - - Runnable getCallback() { - return mItemCallback; - } - - public MenuItem setCallback(Runnable callback) { - mItemCallback = callback; - return this; - } - - public char getAlphabeticShortcut() { - return mShortcutAlphabeticChar; - } - - public MenuItem setAlphabeticShortcut(char alphaChar) { - if (mShortcutAlphabeticChar == alphaChar) return this; - - mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); - - mMenu.onItemsChanged(false); - - return this; - } - - public char getNumericShortcut() { - return mShortcutNumericChar; - } - - public MenuItem setNumericShortcut(char numericChar) { - if (mShortcutNumericChar == numericChar) return this; - - mShortcutNumericChar = numericChar; - - mMenu.onItemsChanged(false); - - return this; - } - - public MenuItem setShortcut(char numericChar, char alphaChar) { - mShortcutNumericChar = numericChar; - mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); - - mMenu.onItemsChanged(false); - - return this; - } - - /** - * @return The active shortcut (based on QWERTY-mode of the menu). - */ - char getShortcut() { - return (mMenu.isQwertyMode() ? mShortcutAlphabeticChar : mShortcutNumericChar); - } - - /** - * @return The label to show for the shortcut. This includes the chording - * key (for example 'Menu+a'). Also, any non-human readable - * characters should be human readable (for example 'Menu+enter'). - */ - String getShortcutLabel() { - - char shortcut = getShortcut(); - if (shortcut == 0) { - return ""; - } - - StringBuilder sb = new StringBuilder(sPrependShortcutLabel); - switch (shortcut) { - - case '\n': - sb.append(sEnterShortcutLabel); - break; - - case '\b': - sb.append(sDeleteShortcutLabel); - break; - - case ' ': - sb.append(sSpaceShortcutLabel); - break; - - default: - sb.append(shortcut); - break; - } - - return sb.toString(); - } - - /** - * @return Whether this menu item should be showing shortcuts (depends on - * whether the menu should show shortcuts and whether this item has - * a shortcut defined) - */ - boolean shouldShowShortcut() { - // Show shortcuts if the menu is supposed to show shortcuts AND this item has a shortcut - return mMenu.isShortcutsVisible() && (getShortcut() != 0); - } - - public SubMenu getSubMenu() { - return mSubMenu; - } - - public boolean hasSubMenu() { - return mSubMenu != null; - } - - void setSubMenu(SubMenuBuilder subMenu) { - mSubMenu = subMenu; - - subMenu.setHeaderTitle(getTitle()); - } - - @ViewDebug.CapturedViewProperty - public CharSequence getTitle() { - return mTitle; - } - - /** - * Gets the title for a particular {@link ItemView} - * - * @param itemView The ItemView that is receiving the title - * @return Either the title or condensed title based on what the ItemView - * prefers - */ - CharSequence getTitleForItemView(MenuView.ItemView itemView) { - return ((itemView != null) && itemView.prefersCondensedTitle()) - ? getTitleCondensed() - : getTitle(); - } - - public MenuItem setTitle(CharSequence title) { - mTitle = title; - - mMenu.onItemsChanged(false); - - if (mSubMenu != null) { - mSubMenu.setHeaderTitle(title); - } - - return this; - } - - public MenuItem setTitle(int title) { - return setTitle(mMenu.getContext().getString(title)); - } - - public CharSequence getTitleCondensed() { - return mTitleCondensed != null ? mTitleCondensed : mTitle; - } - - public MenuItem setTitleCondensed(CharSequence title) { - mTitleCondensed = title; - - // Could use getTitle() in the loop below, but just cache what it would do here - if (title == null) { - title = mTitle; - } - - mMenu.onItemsChanged(false); - - return this; - } - - public Drawable getIcon() { - if (mIconDrawable != null) { - return mIconDrawable; - } - - if (mIconResId != NO_ICON) { - return mMenu.getResources().getDrawable(mIconResId); - } - - return null; - } - - public MenuItem setIcon(Drawable icon) { - mIconResId = NO_ICON; - mIconDrawable = icon; - mMenu.onItemsChanged(false); - - return this; - } - - public MenuItem setIcon(int iconResId) { - mIconDrawable = null; - mIconResId = iconResId; - - // If we have a view, we need to push the Drawable to them - mMenu.onItemsChanged(false); - - return this; - } - - public boolean isCheckable() { - return (mFlags & CHECKABLE) == CHECKABLE; - } - - public MenuItem setCheckable(boolean checkable) { - final int oldFlags = mFlags; - mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0); - if (oldFlags != mFlags) { - mMenu.onItemsChanged(false); - } - - return this; - } - - public void setExclusiveCheckable(boolean exclusive) { - mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0); - } - - public boolean isExclusiveCheckable() { - return (mFlags & EXCLUSIVE) != 0; - } - - public boolean isChecked() { - return (mFlags & CHECKED) == CHECKED; - } - - public MenuItem setChecked(boolean checked) { - if ((mFlags & EXCLUSIVE) != 0) { - // Call the method on the Menu since it knows about the others in this - // exclusive checkable group - mMenu.setExclusiveItemChecked(this); - } else { - setCheckedInt(checked); - } - - return this; - } - - void setCheckedInt(boolean checked) { - final int oldFlags = mFlags; - mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0); - if (oldFlags != mFlags) { - mMenu.onItemsChanged(false); - } - } - - public boolean isVisible() { - return (mFlags & HIDDEN) == 0; - } - - /** - * Changes the visibility of the item. This method DOES NOT notify the - * parent menu of a change in this item, so this should only be called from - * methods that will eventually trigger this change. If unsure, use {@link #setVisible(boolean)} - * instead. - * - * @param shown Whether to show (true) or hide (false). - * @return Whether the item's shown state was changed - */ - boolean setVisibleInt(boolean shown) { - final int oldFlags = mFlags; - mFlags = (mFlags & ~HIDDEN) | (shown ? 0 : HIDDEN); - return oldFlags != mFlags; - } - - public MenuItem setVisible(boolean shown) { - // Try to set the shown state to the given state. If the shown state was changed - // (i.e. the previous state isn't the same as given state), notify the parent menu that - // the shown state has changed for this item - if (setVisibleInt(shown)) mMenu.onItemVisibleChanged(this); - - return this; - } - - public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener clickListener) { - mClickListener = clickListener; - return this; - } - - @Override - public String toString() { - return mTitle.toString(); - } - - void setMenuInfo(ContextMenuInfo menuInfo) { - mMenuInfo = menuInfo; - } - - public ContextMenuInfo getMenuInfo() { - return mMenuInfo; - } - - public void actionFormatChanged() { - mMenu.onItemActionRequestChanged(this); - } - - /** - * @return Whether the menu should show icons for menu items. - */ - public boolean shouldShowIcon() { - return mMenu.getOptionalIconsVisible(); - } - - public boolean isActionButton() { - return (mFlags & IS_ACTION) == IS_ACTION; - } - - public boolean requestsActionButton() { - return (mShowAsAction & SHOW_AS_ACTION_IF_ROOM) == SHOW_AS_ACTION_IF_ROOM; - } - - public boolean requiresActionButton() { - return (mShowAsAction & SHOW_AS_ACTION_ALWAYS) == SHOW_AS_ACTION_ALWAYS; - } - - public void setIsActionButton(boolean isActionButton) { - if (isActionButton) { - mFlags |= IS_ACTION; - } else { - mFlags &= ~IS_ACTION; - } - } - - public boolean showsTextAsAction() { - return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT; - } - - public void setShowAsAction(int actionEnum) { - switch (actionEnum & SHOW_AS_ACTION_MASK) { - case SHOW_AS_ACTION_ALWAYS: - case SHOW_AS_ACTION_IF_ROOM: - case SHOW_AS_ACTION_NEVER: - // Looks good! - break; - - default: - // Mutually exclusive options selected! - throw new IllegalArgumentException("SHOW_AS_ACTION_ALWAYS, SHOW_AS_ACTION_IF_ROOM," - + " and SHOW_AS_ACTION_NEVER are mutually exclusive."); - } - mShowAsAction = actionEnum; - mMenu.onItemActionRequestChanged(this); - } - - public MenuItem setActionView(View view) { - mActionView = view; - mActionProvider = null; - if (view != null && view.getId() == View.NO_ID && mId > 0) { - view.setId(mId); - } - mMenu.onItemActionRequestChanged(this); - return this; - } - - public MenuItem setActionView(int resId) { - final Context context = mMenu.getContext(); - final LayoutInflater inflater = LayoutInflater.from(context); - setActionView(inflater.inflate(resId, new LinearLayout(context), false)); - return this; - } - - public View getActionView() { - if (mActionView != null) { - return mActionView; - } else if (mActionProvider != null) { - mActionView = mActionProvider.onCreateActionView(); - return mActionView; - } else { - return null; - } - } - - public ActionProvider getActionProvider() { - return mActionProvider; - } - - public MenuItem setActionProvider(ActionProvider actionProvider) { - mActionView = null; - mActionProvider = actionProvider; - mMenu.onItemsChanged(true); // Measurement can be changed - return this; - } - - @Override - public MenuItem setShowAsActionFlags(int actionEnum) { - setShowAsAction(actionEnum); - return this; - } - - @Override - public boolean expandActionView() { - if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0 || mActionView == null) { - return false; - } - - if (mOnActionExpandListener == null || - mOnActionExpandListener.onMenuItemActionExpand(this)) { - return mMenu.expandItemActionView(this); - } - - return false; - } - - @Override - public boolean collapseActionView() { - if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0) { - return false; - } - if (mActionView == null) { - // We're already collapsed if we have no action view. - return true; - } - - if (mOnActionExpandListener == null || - mOnActionExpandListener.onMenuItemActionCollapse(this)) { - return mMenu.collapseItemActionView(this); - } - - return false; - } - - @Override - public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { - mOnActionExpandListener = listener; - return this; - } - - public boolean hasCollapsibleActionView() { - return (mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) != 0 && mActionView != null; - } - - public void setActionViewExpanded(boolean isExpanded) { - mIsActionViewExpanded = isExpanded; - mMenu.onItemsChanged(false); - } - - public boolean isActionViewExpanded() { - return mIsActionViewExpanded; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java deleted file mode 100644 index aaf2997b7..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java +++ /dev/null @@ -1,310 +0,0 @@ -package com.actionbarsherlock.internal.view.menu; - -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.View; -import com.actionbarsherlock.internal.view.ActionProviderWrapper; -import com.actionbarsherlock.internal.widget.CollapsibleActionViewWrapper; -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.view.CollapsibleActionView; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -public class MenuItemWrapper implements MenuItem, android.view.MenuItem.OnMenuItemClickListener { - private final android.view.MenuItem mNativeItem; - private SubMenu mSubMenu = null; - private OnMenuItemClickListener mMenuItemClickListener = null; - private OnActionExpandListener mActionExpandListener = null; - private android.view.MenuItem.OnActionExpandListener mNativeActionExpandListener = null; - - - public MenuItemWrapper(android.view.MenuItem nativeItem) { - if (nativeItem == null) { - throw new IllegalStateException("Wrapped menu item cannot be null."); - } - mNativeItem = nativeItem; - } - - - @Override - public int getItemId() { - return mNativeItem.getItemId(); - } - - @Override - public int getGroupId() { - return mNativeItem.getGroupId(); - } - - @Override - public int getOrder() { - return mNativeItem.getOrder(); - } - - @Override - public MenuItem setTitle(CharSequence title) { - mNativeItem.setTitle(title); - return this; - } - - @Override - public MenuItem setTitle(int title) { - mNativeItem.setTitle(title); - return this; - } - - @Override - public CharSequence getTitle() { - return mNativeItem.getTitle(); - } - - @Override - public MenuItem setTitleCondensed(CharSequence title) { - mNativeItem.setTitleCondensed(title); - return this; - } - - @Override - public CharSequence getTitleCondensed() { - return mNativeItem.getTitleCondensed(); - } - - @Override - public MenuItem setIcon(Drawable icon) { - mNativeItem.setIcon(icon); - return this; - } - - @Override - public MenuItem setIcon(int iconRes) { - mNativeItem.setIcon(iconRes); - return this; - } - - @Override - public Drawable getIcon() { - return mNativeItem.getIcon(); - } - - @Override - public MenuItem setIntent(Intent intent) { - mNativeItem.setIntent(intent); - return this; - } - - @Override - public Intent getIntent() { - return mNativeItem.getIntent(); - } - - @Override - public MenuItem setShortcut(char numericChar, char alphaChar) { - mNativeItem.setShortcut(numericChar, alphaChar); - return this; - } - - @Override - public MenuItem setNumericShortcut(char numericChar) { - mNativeItem.setNumericShortcut(numericChar); - return this; - } - - @Override - public char getNumericShortcut() { - return mNativeItem.getNumericShortcut(); - } - - @Override - public MenuItem setAlphabeticShortcut(char alphaChar) { - mNativeItem.setAlphabeticShortcut(alphaChar); - return this; - } - - @Override - public char getAlphabeticShortcut() { - return mNativeItem.getAlphabeticShortcut(); - } - - @Override - public MenuItem setCheckable(boolean checkable) { - mNativeItem.setCheckable(checkable); - return this; - } - - @Override - public boolean isCheckable() { - return mNativeItem.isCheckable(); - } - - @Override - public MenuItem setChecked(boolean checked) { - mNativeItem.setChecked(checked); - return this; - } - - @Override - public boolean isChecked() { - return mNativeItem.isChecked(); - } - - @Override - public MenuItem setVisible(boolean visible) { - mNativeItem.setVisible(visible); - return this; - } - - @Override - public boolean isVisible() { - return mNativeItem.isVisible(); - } - - @Override - public MenuItem setEnabled(boolean enabled) { - mNativeItem.setEnabled(enabled); - return this; - } - - @Override - public boolean isEnabled() { - return mNativeItem.isEnabled(); - } - - @Override - public boolean hasSubMenu() { - return mNativeItem.hasSubMenu(); - } - - @Override - public SubMenu getSubMenu() { - if (hasSubMenu() && (mSubMenu == null)) { - mSubMenu = new SubMenuWrapper(mNativeItem.getSubMenu()); - } - return mSubMenu; - } - - @Override - public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) { - mMenuItemClickListener = menuItemClickListener; - //Register ourselves as the listener to proxy - mNativeItem.setOnMenuItemClickListener(this); - return this; - } - - @Override - public boolean onMenuItemClick(android.view.MenuItem item) { - if (mMenuItemClickListener != null) { - return mMenuItemClickListener.onMenuItemClick(this); - } - return false; - } - - @Override - public ContextMenuInfo getMenuInfo() { - return mNativeItem.getMenuInfo(); - } - - @Override - public void setShowAsAction(int actionEnum) { - mNativeItem.setShowAsAction(actionEnum); - } - - @Override - public MenuItem setShowAsActionFlags(int actionEnum) { - mNativeItem.setShowAsActionFlags(actionEnum); - return this; - } - - @Override - public MenuItem setActionView(View view) { - if (view != null && view instanceof CollapsibleActionView) { - view = new CollapsibleActionViewWrapper(view); - } - mNativeItem.setActionView(view); - return this; - } - - @Override - public MenuItem setActionView(int resId) { - //Allow the native menu to inflate the resource - mNativeItem.setActionView(resId); - if (resId != 0) { - //Get newly created view - View view = mNativeItem.getActionView(); - if (view instanceof CollapsibleActionView) { - //Wrap it and re-set it - mNativeItem.setActionView(new CollapsibleActionViewWrapper(view)); - } - } - return this; - } - - @Override - public View getActionView() { - View actionView = mNativeItem.getActionView(); - if (actionView instanceof CollapsibleActionViewWrapper) { - return ((CollapsibleActionViewWrapper)actionView).unwrap(); - } - return actionView; - } - - @Override - public MenuItem setActionProvider(ActionProvider actionProvider) { - mNativeItem.setActionProvider(new ActionProviderWrapper(actionProvider)); - return this; - } - - @Override - public ActionProvider getActionProvider() { - android.view.ActionProvider nativeProvider = mNativeItem.getActionProvider(); - if (nativeProvider != null && nativeProvider instanceof ActionProviderWrapper) { - return ((ActionProviderWrapper)nativeProvider).unwrap(); - } - return null; - } - - @Override - public boolean expandActionView() { - return mNativeItem.expandActionView(); - } - - @Override - public boolean collapseActionView() { - return mNativeItem.collapseActionView(); - } - - @Override - public boolean isActionViewExpanded() { - return mNativeItem.isActionViewExpanded(); - } - - @Override - public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { - mActionExpandListener = listener; - - if (mNativeActionExpandListener == null) { - mNativeActionExpandListener = new android.view.MenuItem.OnActionExpandListener() { - @Override - public boolean onMenuItemActionExpand(android.view.MenuItem menuItem) { - if (mActionExpandListener != null) { - return mActionExpandListener.onMenuItemActionExpand(MenuItemWrapper.this); - } - return false; - } - - @Override - public boolean onMenuItemActionCollapse(android.view.MenuItem menuItem) { - if (mActionExpandListener != null) { - return mActionExpandListener.onMenuItemActionCollapse(MenuItemWrapper.this); - } - return false; - } - }; - - //Register our inner-class as the listener to proxy method calls - mNativeItem.setOnActionExpandListener(mNativeActionExpandListener); - } - - return this; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java deleted file mode 100644 index f030de310..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import java.util.ArrayList; -import android.content.Context; -import android.content.res.Resources; -import android.database.DataSetObserver; -import android.os.Parcelable; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.ListAdapter; -import android.widget.PopupWindow; -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.view.View_HasStateListenerSupport; -import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener; -import com.actionbarsherlock.internal.widget.IcsListPopupWindow; -import com.actionbarsherlock.view.MenuItem; - -/** - * Presents a menu as a small, simple popup anchored to another view. - * @hide - */ -public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener, - ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener, - View_OnAttachStateChangeListener, MenuPresenter { - //UNUSED private static final String TAG = "MenuPopupHelper"; - - static final int ITEM_LAYOUT = R.layout.abs__popup_menu_item_layout; - - private Context mContext; - private LayoutInflater mInflater; - private IcsListPopupWindow mPopup; - private MenuBuilder mMenu; - private int mPopupMaxWidth; - private View mAnchorView; - private boolean mOverflowOnly; - private ViewTreeObserver mTreeObserver; - - private MenuAdapter mAdapter; - - private Callback mPresenterCallback; - - boolean mForceShowIcon; - - private ViewGroup mMeasureParent; - - public MenuPopupHelper(Context context, MenuBuilder menu) { - this(context, menu, null, false); - } - - public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) { - this(context, menu, anchorView, false); - } - - public MenuPopupHelper(Context context, MenuBuilder menu, - View anchorView, boolean overflowOnly) { - mContext = context; - mInflater = LayoutInflater.from(context); - mMenu = menu; - mOverflowOnly = overflowOnly; - - final Resources res = context.getResources(); - mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2, - res.getDimensionPixelSize(R.dimen.abs__config_prefDialogWidth)); - - mAnchorView = anchorView; - - menu.addMenuPresenter(this); - } - - public void setAnchorView(View anchor) { - mAnchorView = anchor; - } - - public void setForceShowIcon(boolean forceShow) { - mForceShowIcon = forceShow; - } - - public void show() { - if (!tryShow()) { - throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); - } - } - - public boolean tryShow() { - mPopup = new IcsListPopupWindow(mContext, null, R.attr.popupMenuStyle); - mPopup.setOnDismissListener(this); - mPopup.setOnItemClickListener(this); - - mAdapter = new MenuAdapter(mMenu); - mPopup.setAdapter(mAdapter); - mPopup.setModal(true); - - View anchor = mAnchorView; - if (anchor != null) { - final boolean addGlobalListener = mTreeObserver == null; - mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest - if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this); - ((View_HasStateListenerSupport)anchor).addOnAttachStateChangeListener(this); - mPopup.setAnchorView(anchor); - } else { - return false; - } - - mPopup.setContentWidth(Math.min(measureContentWidth(mAdapter), mPopupMaxWidth)); - mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); - mPopup.show(); - mPopup.getListView().setOnKeyListener(this); - return true; - } - - public void dismiss() { - if (isShowing()) { - mPopup.dismiss(); - } - } - - public void onDismiss() { - mPopup = null; - mMenu.close(); - if (mTreeObserver != null) { - if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver(); - mTreeObserver.removeGlobalOnLayoutListener(this); - mTreeObserver = null; - } - ((View_HasStateListenerSupport)mAnchorView).removeOnAttachStateChangeListener(this); - } - - public boolean isShowing() { - return mPopup != null && mPopup.isShowing(); - } - - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - MenuAdapter adapter = mAdapter; - adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0); - } - - public boolean onKey(View v, int keyCode, KeyEvent event) { - if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) { - dismiss(); - return true; - } - return false; - } - - private int measureContentWidth(ListAdapter adapter) { - // Menus don't tend to be long, so this is more sane than it looks. - int width = 0; - View itemView = null; - int itemType = 0; - final int widthMeasureSpec = - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int heightMeasureSpec = - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int count = adapter.getCount(); - for (int i = 0; i < count; i++) { - final int positionType = adapter.getItemViewType(i); - if (positionType != itemType) { - itemType = positionType; - itemView = null; - } - if (mMeasureParent == null) { - mMeasureParent = new FrameLayout(mContext); - } - itemView = adapter.getView(i, itemView, mMeasureParent); - itemView.measure(widthMeasureSpec, heightMeasureSpec); - width = Math.max(width, itemView.getMeasuredWidth()); - } - return width; - } - - @Override - public void onGlobalLayout() { - if (isShowing()) { - final View anchor = mAnchorView; - if (anchor == null || !anchor.isShown()) { - dismiss(); - } else if (isShowing()) { - // Recompute window size and position - mPopup.show(); - } - } - } - - @Override - public void onViewAttachedToWindow(View v) { - } - - @Override - public void onViewDetachedFromWindow(View v) { - if (mTreeObserver != null) { - if (!mTreeObserver.isAlive()) mTreeObserver = v.getViewTreeObserver(); - mTreeObserver.removeGlobalOnLayoutListener(this); - } - ((View_HasStateListenerSupport)v).removeOnAttachStateChangeListener(this); - } - - @Override - public void initForMenu(Context context, MenuBuilder menu) { - // Don't need to do anything; we added as a presenter in the constructor. - } - - @Override - public MenuView getMenuView(ViewGroup root) { - throw new UnsupportedOperationException("MenuPopupHelpers manage their own views"); - } - - @Override - public void updateMenuView(boolean cleared) { - if (mAdapter != null) mAdapter.notifyDataSetChanged(); - } - - @Override - public void setCallback(Callback cb) { - mPresenterCallback = cb; - } - - @Override - public boolean onSubMenuSelected(SubMenuBuilder subMenu) { - if (subMenu.hasVisibleItems()) { - MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false); - subPopup.setCallback(mPresenterCallback); - - boolean preserveIconSpacing = false; - final int count = subMenu.size(); - for (int i = 0; i < count; i++) { - MenuItem childItem = subMenu.getItem(i); - if (childItem.isVisible() && childItem.getIcon() != null) { - preserveIconSpacing = true; - break; - } - } - subPopup.setForceShowIcon(preserveIconSpacing); - - if (subPopup.tryShow()) { - if (mPresenterCallback != null) { - mPresenterCallback.onOpenSubMenu(subMenu); - } - return true; - } - } - return false; - } - - @Override - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - // Only care about the (sub)menu we're presenting. - if (menu != mMenu) return; - - dismiss(); - if (mPresenterCallback != null) { - mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); - } - } - - @Override - public boolean flagActionItems() { - return false; - } - - public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { - return false; - } - - public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { - return false; - } - - @Override - public int getId() { - return 0; - } - - @Override - public Parcelable onSaveInstanceState() { - return null; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - } - - private class MenuAdapter extends BaseAdapter { - private MenuBuilder mAdapterMenu; - private int mExpandedIndex = -1; - - public MenuAdapter(MenuBuilder menu) { - mAdapterMenu = menu; - registerDataSetObserver(new ExpandedIndexObserver()); - findExpandedIndex(); - } - - public int getCount() { - ArrayList items = mOverflowOnly ? - mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); - if (mExpandedIndex < 0) { - return items.size(); - } - return items.size() - 1; - } - - public MenuItemImpl getItem(int position) { - ArrayList items = mOverflowOnly ? - mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); - if (mExpandedIndex >= 0 && position >= mExpandedIndex) { - position++; - } - return items.get(position); - } - - public long getItemId(int position) { - // Since a menu item's ID is optional, we'll use the position as an - // ID for the item in the AdapterView - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); - } - - MenuView.ItemView itemView = (MenuView.ItemView) convertView; - if (mForceShowIcon) { - ((ListMenuItemView) convertView).setForceShowIcon(true); - } - itemView.initialize(getItem(position), 0); - return convertView; - } - - void findExpandedIndex() { - final MenuItemImpl expandedItem = mMenu.getExpandedItem(); - if (expandedItem != null) { - final ArrayList items = mMenu.getNonActionItems(); - final int count = items.size(); - for (int i = 0; i < count; i++) { - final MenuItemImpl item = items.get(i); - if (item == expandedItem) { - mExpandedIndex = i; - return; - } - } - } - mExpandedIndex = -1; - } - } - - private class ExpandedIndexObserver extends DataSetObserver { - @Override - public void onChanged() { - mAdapter.findExpandedIndex(); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java deleted file mode 100644 index c3f35472c..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import android.content.Context; -import android.os.Parcelable; -import android.view.ViewGroup; - -/** - * A MenuPresenter is responsible for building views for a Menu object. - * It takes over some responsibility from the old style monolithic MenuBuilder class. - */ -public interface MenuPresenter { - /** - * Called by menu implementation to notify another component of open/close events. - */ - public interface Callback { - /** - * Called when a menu is closing. - * @param menu - * @param allMenusAreClosing - */ - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing); - - /** - * Called when a submenu opens. Useful for notifying the application - * of menu state so that it does not attempt to hide the action bar - * while a submenu is open or similar. - * - * @param subMenu Submenu currently being opened - * @return true if the Callback will handle presenting the submenu, false if - * the presenter should attempt to do so. - */ - public boolean onOpenSubMenu(MenuBuilder subMenu); - } - - /** - * Initialize this presenter for the given context and menu. - * This method is called by MenuBuilder when a presenter is - * added. See {@link MenuBuilder#addMenuPresenter(MenuPresenter)} - * - * @param context Context for this presenter; used for view creation and resource management - * @param menu Menu to host - */ - public void initForMenu(Context context, MenuBuilder menu); - - /** - * Retrieve a MenuView to display the menu specified in - * {@link #initForMenu(Context, Menu)}. - * - * @param root Intended parent of the MenuView. - * @return A freshly created MenuView. - */ - public MenuView getMenuView(ViewGroup root); - - /** - * Update the menu UI in response to a change. Called by - * MenuBuilder during the normal course of operation. - * - * @param cleared true if the menu was entirely cleared - */ - public void updateMenuView(boolean cleared); - - /** - * Set a callback object that will be notified of menu events - * related to this specific presentation. - * @param cb Callback that will be notified of future events - */ - public void setCallback(Callback cb); - - /** - * Called by Menu implementations to indicate that a submenu item - * has been selected. An active Callback should be notified, and - * if applicable the presenter should present the submenu. - * - * @param subMenu SubMenu being opened - * @return true if the the event was handled, false otherwise. - */ - public boolean onSubMenuSelected(SubMenuBuilder subMenu); - - /** - * Called by Menu implementations to indicate that a menu or submenu is - * closing. Presenter implementations should close the representation - * of the menu indicated as necessary and notify a registered callback. - * - * @param menu Menu or submenu that is closing. - * @param allMenusAreClosing True if all associated menus are closing. - */ - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing); - - /** - * Called by Menu implementations to flag items that will be shown as actions. - * @return true if this presenter changed the action status of any items. - */ - public boolean flagActionItems(); - - /** - * Called when a menu item with a collapsable action view should expand its action view. - * - * @param menu Menu containing the item to be expanded - * @param item Item to be expanded - * @return true if this presenter expanded the action view, false otherwise. - */ - public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item); - - /** - * Called when a menu item with a collapsable action view should collapse its action view. - * - * @param menu Menu containing the item to be collapsed - * @param item Item to be collapsed - * @return true if this presenter collapsed the action view, false otherwise. - */ - public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item); - - /** - * Returns an ID for determining how to save/restore instance state. - * @return a valid ID value. - */ - public int getId(); - - /** - * Returns a Parcelable describing the current state of the presenter. - * It will be passed to the {@link #onRestoreInstanceState(Parcelable)} - * method of the presenter sharing the same ID later. - * @return The saved instance state - */ - public Parcelable onSaveInstanceState(); - - /** - * Supplies the previously saved instance state to be restored. - * @param state The previously saved instance state - */ - public void onRestoreInstanceState(Parcelable state); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java deleted file mode 100644 index 323ba2d88..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import android.graphics.drawable.Drawable; - -/** - * Minimal interface for a menu view. {@link #initialize(MenuBuilder)} must be called for the - * menu to be functional. - * - * @hide - */ -public interface MenuView { - /** - * Initializes the menu to the given menu. This should be called after the - * view is inflated. - * - * @param menu The menu that this MenuView should display. - */ - public void initialize(MenuBuilder menu); - - /** - * Returns the default animations to be used for this menu when entering/exiting. - * @return A resource ID for the default animations to be used for this menu. - */ - public int getWindowAnimations(); - - /** - * Minimal interface for a menu item view. {@link #initialize(MenuItemImpl, int)} must be called - * for the item to be functional. - */ - public interface ItemView { - /** - * Initializes with the provided MenuItemData. This should be called after the view is - * inflated. - * @param itemData The item that this ItemView should display. - * @param menuType The type of this menu, one of - * {@link MenuBuilder#TYPE_ICON}, {@link MenuBuilder#TYPE_EXPANDED}, - * {@link MenuBuilder#TYPE_DIALOG}). - */ - public void initialize(MenuItemImpl itemData, int menuType); - - /** - * Gets the item data that this view is displaying. - * @return the item data, or null if there is not one - */ - public MenuItemImpl getItemData(); - - /** - * Sets the title of the item view. - * @param title The title to set. - */ - public void setTitle(CharSequence title); - - /** - * Sets the enabled state of the item view. - * @param enabled Whether the item view should be enabled. - */ - public void setEnabled(boolean enabled); - - /** - * Displays the checkbox for the item view. This does not ensure the item view will be - * checked, for that use {@link #setChecked}. - * @param checkable Whether to display the checkbox or to hide it - */ - public void setCheckable(boolean checkable); - - /** - * Checks the checkbox for the item view. If the checkbox is hidden, it will NOT be - * made visible, call {@link #setCheckable(boolean)} for that. - * @param checked Whether the checkbox should be checked - */ - public void setChecked(boolean checked); - - /** - * Sets the shortcut for the item. - * @param showShortcut Whether a shortcut should be shown(if false, the value of - * shortcutKey should be ignored). - * @param shortcutKey The shortcut key that should be shown on the ItemView. - */ - public void setShortcut(boolean showShortcut, char shortcutKey); - - /** - * Set the icon of this item view. - * @param icon The icon of this item. null to hide the icon. - */ - public void setIcon(Drawable icon); - - /** - * Whether this item view prefers displaying the condensed title rather - * than the normal title. If a condensed title is not available, the - * normal title will be used. - * - * @return Whether this item view prefers displaying the condensed - * title. - */ - public boolean prefersCondensedTitle(); - - /** - * Whether this item view shows an icon. - * - * @return Whether this item view shows an icon. - */ - public boolean showsIcon(); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java deleted file mode 100644 index 3d4dd42fd..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.actionbarsherlock.internal.view.menu; - -import java.util.WeakHashMap; -import android.content.ComponentName; -import android.content.Intent; -import android.view.KeyEvent; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -public class MenuWrapper implements Menu { - private final android.view.Menu mNativeMenu; - - private final WeakHashMap mNativeMap = - new WeakHashMap(); - - - public MenuWrapper(android.view.Menu nativeMenu) { - mNativeMenu = nativeMenu; - } - - public android.view.Menu unwrap() { - return mNativeMenu; - } - - private MenuItem addInternal(android.view.MenuItem nativeItem) { - MenuItem item = new MenuItemWrapper(nativeItem); - mNativeMap.put(nativeItem, item); - return item; - } - - @Override - public MenuItem add(CharSequence title) { - return addInternal(mNativeMenu.add(title)); - } - - @Override - public MenuItem add(int titleRes) { - return addInternal(mNativeMenu.add(titleRes)); - } - - @Override - public MenuItem add(int groupId, int itemId, int order, CharSequence title) { - return addInternal(mNativeMenu.add(groupId, itemId, order, title)); - } - - @Override - public MenuItem add(int groupId, int itemId, int order, int titleRes) { - return addInternal(mNativeMenu.add(groupId, itemId, order, titleRes)); - } - - private SubMenu addInternal(android.view.SubMenu nativeSubMenu) { - SubMenu subMenu = new SubMenuWrapper(nativeSubMenu); - android.view.MenuItem nativeItem = nativeSubMenu.getItem(); - MenuItem item = subMenu.getItem(); - mNativeMap.put(nativeItem, item); - return subMenu; - } - - @Override - public SubMenu addSubMenu(CharSequence title) { - return addInternal(mNativeMenu.addSubMenu(title)); - } - - @Override - public SubMenu addSubMenu(int titleRes) { - return addInternal(mNativeMenu.addSubMenu(titleRes)); - } - - @Override - public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { - return addInternal(mNativeMenu.addSubMenu(groupId, itemId, order, title)); - } - - @Override - public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { - return addInternal(mNativeMenu.addSubMenu(groupId, itemId, order, titleRes)); - } - - @Override - public int addIntentOptions(int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { - int result; - if (outSpecificItems != null) { - android.view.MenuItem[] nativeOutItems = new android.view.MenuItem[outSpecificItems.length]; - result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, nativeOutItems); - for (int i = 0, length = outSpecificItems.length; i < length; i++) { - outSpecificItems[i] = new MenuItemWrapper(nativeOutItems[i]); - } - } else { - result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, null); - } - return result; - } - - @Override - public void removeItem(int id) { - mNativeMenu.removeItem(id); - } - - @Override - public void removeGroup(int groupId) { - mNativeMenu.removeGroup(groupId); - } - - @Override - public void clear() { - mNativeMap.clear(); - mNativeMenu.clear(); - } - - @Override - public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { - mNativeMenu.setGroupCheckable(group, checkable, exclusive); - } - - @Override - public void setGroupVisible(int group, boolean visible) { - mNativeMenu.setGroupVisible(group, visible); - } - - @Override - public void setGroupEnabled(int group, boolean enabled) { - mNativeMenu.setGroupEnabled(group, enabled); - } - - @Override - public boolean hasVisibleItems() { - return mNativeMenu.hasVisibleItems(); - } - - @Override - public MenuItem findItem(int id) { - android.view.MenuItem nativeItem = mNativeMenu.findItem(id); - return findItem(nativeItem); - } - - public MenuItem findItem(android.view.MenuItem nativeItem) { - if (nativeItem == null) { - return null; - } - - MenuItem wrapped = mNativeMap.get(nativeItem); - if (wrapped != null) { - return wrapped; - } - - return addInternal(nativeItem); - } - - @Override - public int size() { - return mNativeMenu.size(); - } - - @Override - public MenuItem getItem(int index) { - android.view.MenuItem nativeItem = mNativeMenu.getItem(index); - return findItem(nativeItem); - } - - @Override - public void close() { - mNativeMenu.close(); - } - - @Override - public boolean performShortcut(int keyCode, KeyEvent event, int flags) { - return mNativeMenu.performShortcut(keyCode, event, flags); - } - - @Override - public boolean isShortcutKey(int keyCode, KeyEvent event) { - return mNativeMenu.isShortcutKey(keyCode, event); - } - - @Override - public boolean performIdentifierAction(int id, int flags) { - return mNativeMenu.performIdentifierAction(id, flags); - } - - @Override - public void setQwertyMode(boolean isQwerty) { - mNativeMenu.setQwertyMode(isQwerty); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java deleted file mode 100644 index 6679cf386..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.view.menu; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.view.View; - -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -/** - * The model for a sub menu, which is an extension of the menu. Most methods are proxied to - * the parent menu. - */ -public class SubMenuBuilder extends MenuBuilder implements SubMenu { - private MenuBuilder mParentMenu; - private MenuItemImpl mItem; - - public SubMenuBuilder(Context context, MenuBuilder parentMenu, MenuItemImpl item) { - super(context); - - mParentMenu = parentMenu; - mItem = item; - } - - @Override - public void setQwertyMode(boolean isQwerty) { - mParentMenu.setQwertyMode(isQwerty); - } - - @Override - public boolean isQwertyMode() { - return mParentMenu.isQwertyMode(); - } - - @Override - public void setShortcutsVisible(boolean shortcutsVisible) { - mParentMenu.setShortcutsVisible(shortcutsVisible); - } - - @Override - public boolean isShortcutsVisible() { - return mParentMenu.isShortcutsVisible(); - } - - public Menu getParentMenu() { - return mParentMenu; - } - - public MenuItem getItem() { - return mItem; - } - - @Override - public void setCallback(Callback callback) { - mParentMenu.setCallback(callback); - } - - @Override - public MenuBuilder getRootMenu() { - return mParentMenu; - } - - @Override - boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) { - return super.dispatchMenuItemSelected(menu, item) || - mParentMenu.dispatchMenuItemSelected(menu, item); - } - - public SubMenu setIcon(Drawable icon) { - mItem.setIcon(icon); - return this; - } - - public SubMenu setIcon(int iconRes) { - mItem.setIcon(iconRes); - return this; - } - - public SubMenu setHeaderIcon(Drawable icon) { - return (SubMenu) super.setHeaderIconInt(icon); - } - - public SubMenu setHeaderIcon(int iconRes) { - return (SubMenu) super.setHeaderIconInt(iconRes); - } - - public SubMenu setHeaderTitle(CharSequence title) { - return (SubMenu) super.setHeaderTitleInt(title); - } - - public SubMenu setHeaderTitle(int titleRes) { - return (SubMenu) super.setHeaderTitleInt(titleRes); - } - - public SubMenu setHeaderView(View view) { - return (SubMenu) super.setHeaderViewInt(view); - } - - @Override - public boolean expandItemActionView(MenuItemImpl item) { - return mParentMenu.expandItemActionView(item); - } - - @Override - public boolean collapseItemActionView(MenuItemImpl item) { - return mParentMenu.collapseItemActionView(item); - } - - @Override - public String getActionViewStatesKey() { - final int itemId = mItem != null ? mItem.getItemId() : 0; - if (itemId == 0) { - return null; - } - return super.getActionViewStatesKey() + ":" + itemId; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java deleted file mode 100644 index 7d307acb1..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.actionbarsherlock.internal.view.menu; - -import android.graphics.drawable.Drawable; -import android.view.View; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.SubMenu; - -public class SubMenuWrapper extends MenuWrapper implements SubMenu { - private final android.view.SubMenu mNativeSubMenu; - private MenuItem mItem = null; - - public SubMenuWrapper(android.view.SubMenu nativeSubMenu) { - super(nativeSubMenu); - mNativeSubMenu = nativeSubMenu; - } - - - @Override - public SubMenu setHeaderTitle(int titleRes) { - mNativeSubMenu.setHeaderTitle(titleRes); - return this; - } - - @Override - public SubMenu setHeaderTitle(CharSequence title) { - mNativeSubMenu.setHeaderTitle(title); - return this; - } - - @Override - public SubMenu setHeaderIcon(int iconRes) { - mNativeSubMenu.setHeaderIcon(iconRes); - return this; - } - - @Override - public SubMenu setHeaderIcon(Drawable icon) { - mNativeSubMenu.setHeaderIcon(icon); - return this; - } - - @Override - public SubMenu setHeaderView(View view) { - mNativeSubMenu.setHeaderView(view); - return this; - } - - @Override - public void clearHeader() { - mNativeSubMenu.clearHeader(); - } - - @Override - public SubMenu setIcon(int iconRes) { - mNativeSubMenu.setIcon(iconRes); - return this; - } - - @Override - public SubMenu setIcon(Drawable icon) { - mNativeSubMenu.setIcon(icon); - return this; - } - - @Override - public MenuItem getItem() { - if (mItem == null) { - mItem = new MenuItemWrapper(mNativeSubMenu.getItem()); - } - return mItem; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java deleted file mode 100644 index 3a4a44675..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.os.Build; -import android.util.AttributeSet; -import android.view.View; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; -import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; -import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; -import com.actionbarsherlock.internal.nineoldandroids.view.NineViewGroup; -import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; -import com.actionbarsherlock.internal.view.menu.ActionMenuView; - -import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; - -public abstract class AbsActionBarView extends NineViewGroup { - protected ActionMenuView mMenuView; - protected ActionMenuPresenter mActionMenuPresenter; - protected ActionBarContainer mSplitView; - protected boolean mSplitActionBar; - protected boolean mSplitWhenNarrow; - protected int mContentHeight; - - final Context mContext; - - protected Animator mVisibilityAnim; - protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); - - private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator(); - - private static final int FADE_DURATION = 200; - - public AbsActionBarView(Context context) { - super(context); - mContext = context; - } - - public AbsActionBarView(Context context, AttributeSet attrs) { - super(context, attrs); - mContext = context; - } - - public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mContext = context; - } - - /* - * Must be public so we can dispatch pre-2.2 via ActionBarImpl. - */ - @Override - public void onConfigurationChanged(Configuration newConfig) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { - super.onConfigurationChanged(newConfig); - } else if (mMenuView != null) { - mMenuView.onConfigurationChanged(newConfig); - } - - // Action bar can change size on configuration changes. - // Reread the desired height from the theme-specified style. - TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, - R.attr.actionBarStyle, 0); - setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); - a.recycle(); - if (mSplitWhenNarrow) { - setSplitActionBar(getResources_getBoolean(getContext(), - R.bool.abs__split_action_bar_is_narrow)); - } - if (mActionMenuPresenter != null) { - mActionMenuPresenter.onConfigurationChanged(newConfig); - } - } - - /** - * Sets whether the bar should be split right now, no questions asked. - * @param split true if the bar should split - */ - public void setSplitActionBar(boolean split) { - mSplitActionBar = split; - } - - /** - * Sets whether the bar should split if we enter a narrow screen configuration. - * @param splitWhenNarrow true if the bar should check to split after a config change - */ - public void setSplitWhenNarrow(boolean splitWhenNarrow) { - mSplitWhenNarrow = splitWhenNarrow; - } - - public void setContentHeight(int height) { - mContentHeight = height; - requestLayout(); - } - - public int getContentHeight() { - return mContentHeight; - } - - public void setSplitView(ActionBarContainer splitView) { - mSplitView = splitView; - } - - /** - * @return Current visibility or if animating, the visibility being animated to. - */ - public int getAnimatedVisibility() { - if (mVisibilityAnim != null) { - return mVisAnimListener.mFinalVisibility; - } - return getVisibility(); - } - - public void animateToVisibility(int visibility) { - if (mVisibilityAnim != null) { - mVisibilityAnim.cancel(); - } - if (visibility == VISIBLE) { - if (getVisibility() != VISIBLE) { - setAlpha(0); - if (mSplitView != null && mMenuView != null) { - mMenuView.setAlpha(0); - } - } - ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); - anim.setDuration(FADE_DURATION); - anim.setInterpolator(sAlphaInterpolator); - if (mSplitView != null && mMenuView != null) { - AnimatorSet set = new AnimatorSet(); - ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1); - splitAnim.setDuration(FADE_DURATION); - set.addListener(mVisAnimListener.withFinalVisibility(visibility)); - set.play(anim).with(splitAnim); - set.start(); - } else { - anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); - anim.start(); - } - } else { - ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); - anim.setDuration(FADE_DURATION); - anim.setInterpolator(sAlphaInterpolator); - if (mSplitView != null && mMenuView != null) { - AnimatorSet set = new AnimatorSet(); - ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0); - splitAnim.setDuration(FADE_DURATION); - set.addListener(mVisAnimListener.withFinalVisibility(visibility)); - set.play(anim).with(splitAnim); - set.start(); - } else { - anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); - anim.start(); - } - } - } - - @Override - public void setVisibility(int visibility) { - if (mVisibilityAnim != null) { - mVisibilityAnim.end(); - } - super.setVisibility(visibility); - } - - public boolean showOverflowMenu() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.showOverflowMenu(); - } - return false; - } - - public void postShowOverflowMenu() { - post(new Runnable() { - public void run() { - showOverflowMenu(); - } - }); - } - - public boolean hideOverflowMenu() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.hideOverflowMenu(); - } - return false; - } - - public boolean isOverflowMenuShowing() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.isOverflowMenuShowing(); - } - return false; - } - - public boolean isOverflowReserved() { - return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved(); - } - - public void dismissPopupMenus() { - if (mActionMenuPresenter != null) { - mActionMenuPresenter.dismissPopupMenus(); - } - } - - protected int measureChildView(View child, int availableWidth, int childSpecHeight, - int spacing) { - child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), - childSpecHeight); - - availableWidth -= child.getMeasuredWidth(); - availableWidth -= spacing; - - return Math.max(0, availableWidth); - } - - protected int positionChild(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x, childTop, x + childWidth, childTop + childHeight); - - return childWidth; - } - - protected int positionChildInverse(View child, int x, int y, int contentHeight) { - int childWidth = child.getMeasuredWidth(); - int childHeight = child.getMeasuredHeight(); - int childTop = y + (contentHeight - childHeight) / 2; - - child.layout(x - childWidth, childTop, x, childTop + childHeight); - - return childWidth; - } - - protected class VisibilityAnimListener implements Animator.AnimatorListener { - private boolean mCanceled = false; - int mFinalVisibility; - - public VisibilityAnimListener withFinalVisibility(int visibility) { - mFinalVisibility = visibility; - return this; - } - - @Override - public void onAnimationStart(Animator animation) { - setVisibility(VISIBLE); - mVisibilityAnim = animation; - mCanceled = false; - } - - @Override - public void onAnimationEnd(Animator animation) { - if (mCanceled) return; - - mVisibilityAnim = null; - setVisibility(mFinalVisibility); - if (mSplitView != null && mMenuView != null) { - mMenuView.setVisibility(mFinalVisibility); - } - } - - @Override - public void onAnimationCancel(Animator animation) { - mCanceled = true; - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java deleted file mode 100644 index 1d9c68b37..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout; - -/** - * This class acts as a container for the action bar view and action mode context views. - * It applies special styles as needed to help handle animated transitions between them. - * @hide - */ -public class ActionBarContainer extends NineFrameLayout { - private boolean mIsTransitioning; - private View mTabContainer; - private ActionBarView mActionBarView; - - private Drawable mBackground; - private Drawable mStackedBackground; - private Drawable mSplitBackground; - private boolean mIsSplit; - private boolean mIsStacked; - - public ActionBarContainer(Context context) { - this(context, null); - } - - public ActionBarContainer(Context context, AttributeSet attrs) { - super(context, attrs); - - setBackgroundDrawable(null); - - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.SherlockActionBar); - mBackground = a.getDrawable(R.styleable.SherlockActionBar_background); - mStackedBackground = a.getDrawable( - R.styleable.SherlockActionBar_backgroundStacked); - - //Fix for issue #379 - if (mStackedBackground instanceof ColorDrawable && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); - Canvas c = new Canvas(bitmap); - mStackedBackground.draw(c); - int color = bitmap.getPixel(0, 0); - bitmap.recycle(); - mStackedBackground = new IcsColorDrawable(color); - } - - if (getId() == R.id.abs__split_action_bar) { - mIsSplit = true; - mSplitBackground = a.getDrawable( - R.styleable.SherlockActionBar_backgroundSplit); - } - a.recycle(); - - setWillNotDraw(mIsSplit ? mSplitBackground == null : - mBackground == null && mStackedBackground == null); - } - - @Override - public void onFinishInflate() { - super.onFinishInflate(); - mActionBarView = (ActionBarView) findViewById(R.id.abs__action_bar); - } - - public void setPrimaryBackground(Drawable bg) { - mBackground = bg; - invalidate(); - } - - public void setStackedBackground(Drawable bg) { - mStackedBackground = bg; - invalidate(); - } - - public void setSplitBackground(Drawable bg) { - mSplitBackground = bg; - invalidate(); - } - - /** - * Set the action bar into a "transitioning" state. While transitioning - * the bar will block focus and touch from all of its descendants. This - * prevents the user from interacting with the bar while it is animating - * in or out. - * - * @param isTransitioning true if the bar is currently transitioning, false otherwise. - */ - public void setTransitioning(boolean isTransitioning) { - mIsTransitioning = isTransitioning; - setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS - : FOCUS_AFTER_DESCENDANTS); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - return mIsTransitioning || super.onInterceptTouchEvent(ev); - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - super.onTouchEvent(ev); - - // An action bar always eats touch events. - return true; - } - - @Override - public boolean onHoverEvent(MotionEvent ev) { - super.onHoverEvent(ev); - - // An action bar always eats hover events. - return true; - } - - public void setTabContainer(ScrollingTabContainerView tabView) { - if (mTabContainer != null) { - removeView(mTabContainer); - } - mTabContainer = tabView; - if (tabView != null) { - addView(tabView); - final ViewGroup.LayoutParams lp = tabView.getLayoutParams(); - lp.width = LayoutParams.MATCH_PARENT; - lp.height = LayoutParams.WRAP_CONTENT; - tabView.setAllowCollapse(false); - } - } - - public View getTabContainer() { - return mTabContainer; - } - - @Override - public void onDraw(Canvas canvas) { - if (getWidth() == 0 || getHeight() == 0) { - return; - } - - if (mIsSplit) { - if (mSplitBackground != null) mSplitBackground.draw(canvas); - } else { - if (mBackground != null) { - mBackground.draw(canvas); - } - if (mStackedBackground != null && mIsStacked) { - mStackedBackground.draw(canvas); - } - } - } - - //This causes the animation reflection to fail on pre-HC platforms - //@Override - //public android.view.ActionMode startActionModeForChild(View child, android.view.ActionMode.Callback callback) { - // // No starting an action mode for an action bar child! (Where would it go?) - // return null; - //} - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - if (mActionBarView == null) return; - - final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams(); - final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 : - mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; - - if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { - final int mode = MeasureSpec.getMode(heightMeasureSpec); - if (mode == MeasureSpec.AT_MOST) { - final int maxHeight = MeasureSpec.getSize(heightMeasureSpec); - setMeasuredDimension(getMeasuredWidth(), - Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(), - maxHeight)); - } - } - } - - @Override - public void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - - final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE; - - if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { - final int containerHeight = getMeasuredHeight(); - final int tabHeight = mTabContainer.getMeasuredHeight(); - - if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) { - // Not showing home, put tabs on top. - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - if (child == mTabContainer) continue; - - if (!mActionBarView.isCollapsed()) { - child.offsetTopAndBottom(tabHeight); - } - } - mTabContainer.layout(l, 0, r, tabHeight); - } else { - mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight); - } - } - - boolean needsInvalidate = false; - if (mIsSplit) { - if (mSplitBackground != null) { - mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); - needsInvalidate = true; - } - } else { - if (mBackground != null) { - mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(), - mActionBarView.getRight(), mActionBarView.getBottom()); - needsInvalidate = true; - } - if ((mIsStacked = hasTabs && mStackedBackground != null)) { - mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(), - mTabContainer.getRight(), mTabContainer.getBottom()); - needsInvalidate = true; - } - } - - if (needsInvalidate) { - invalidate(); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java deleted file mode 100644 index 9ec250f38..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; -import android.view.animation.DecelerateInterpolator; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; -import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; -import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; -import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; -import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; -import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout; -import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; -import com.actionbarsherlock.internal.view.menu.ActionMenuView; -import com.actionbarsherlock.internal.view.menu.MenuBuilder; -import com.actionbarsherlock.view.ActionMode; - -/** - * @hide - */ -public class ActionBarContextView extends AbsActionBarView implements AnimatorListener { - //UNUSED private static final String TAG = "ActionBarContextView"; - - private CharSequence mTitle; - private CharSequence mSubtitle; - - private NineLinearLayout mClose; - private View mCustomView; - private LinearLayout mTitleLayout; - private TextView mTitleView; - private TextView mSubtitleView; - private int mTitleStyleRes; - private int mSubtitleStyleRes; - private Drawable mSplitBackground; - - private Animator mCurrentAnimation; - private boolean mAnimateInOnLayout; - private int mAnimationMode; - - private static final int ANIMATE_IDLE = 0; - private static final int ANIMATE_IN = 1; - private static final int ANIMATE_OUT = 2; - - public ActionBarContextView(Context context) { - this(context, null); - } - - public ActionBarContextView(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.actionModeStyle); - } - - public ActionBarContextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockActionMode, defStyle, 0); - setBackgroundDrawable(a.getDrawable( - R.styleable.SherlockActionMode_background)); - mTitleStyleRes = a.getResourceId( - R.styleable.SherlockActionMode_titleTextStyle, 0); - mSubtitleStyleRes = a.getResourceId( - R.styleable.SherlockActionMode_subtitleTextStyle, 0); - - mContentHeight = a.getLayoutDimension( - R.styleable.SherlockActionMode_height, 0); - - mSplitBackground = a.getDrawable( - R.styleable.SherlockActionMode_backgroundSplit); - - a.recycle(); - } - - @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mActionMenuPresenter != null) { - mActionMenuPresenter.hideOverflowMenu(); - mActionMenuPresenter.hideSubMenus(); - } - } - - @Override - public void setSplitActionBar(boolean split) { - if (mSplitActionBar != split) { - if (mActionMenuPresenter != null) { - // Mode is already active; move everything over and adjust the menu itself. - final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.MATCH_PARENT); - if (!split) { - mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - mMenuView.setBackgroundDrawable(null); - final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); - if (oldParent != null) oldParent.removeView(mMenuView); - addView(mMenuView, layoutParams); - } else { - // Allow full screen width in split mode. - mActionMenuPresenter.setWidthLimit( - getContext().getResources().getDisplayMetrics().widthPixels, true); - // No limit to the item count; use whatever will fit. - mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); - // Span the whole width - layoutParams.width = LayoutParams.MATCH_PARENT; - layoutParams.height = mContentHeight; - mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - mMenuView.setBackgroundDrawable(mSplitBackground); - final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); - if (oldParent != null) oldParent.removeView(mMenuView); - mSplitView.addView(mMenuView, layoutParams); - } - } - super.setSplitActionBar(split); - } - } - - public void setContentHeight(int height) { - mContentHeight = height; - } - - public void setCustomView(View view) { - if (mCustomView != null) { - removeView(mCustomView); - } - mCustomView = view; - if (mTitleLayout != null) { - removeView(mTitleLayout); - mTitleLayout = null; - } - if (view != null) { - addView(view); - } - requestLayout(); - } - - public void setTitle(CharSequence title) { - mTitle = title; - initTitle(); - } - - public void setSubtitle(CharSequence subtitle) { - mSubtitle = subtitle; - initTitle(); - } - - public CharSequence getTitle() { - return mTitle; - } - - public CharSequence getSubtitle() { - return mSubtitle; - } - - private void initTitle() { - if (mTitleLayout == null) { - LayoutInflater inflater = LayoutInflater.from(getContext()); - inflater.inflate(R.layout.abs__action_bar_title_item, this); - mTitleLayout = (LinearLayout) getChildAt(getChildCount() - 1); - mTitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_title); - mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_subtitle); - if (mTitleStyleRes != 0) { - mTitleView.setTextAppearance(mContext, mTitleStyleRes); - } - if (mSubtitleStyleRes != 0) { - mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); - } - } - - mTitleView.setText(mTitle); - mSubtitleView.setText(mSubtitle); - - final boolean hasTitle = !TextUtils.isEmpty(mTitle); - final boolean hasSubtitle = !TextUtils.isEmpty(mSubtitle); - mSubtitleView.setVisibility(hasSubtitle ? VISIBLE : GONE); - mTitleLayout.setVisibility(hasTitle || hasSubtitle ? VISIBLE : GONE); - if (mTitleLayout.getParent() == null) { - addView(mTitleLayout); - } - } - - public void initForMode(final ActionMode mode) { - if (mClose == null) { - LayoutInflater inflater = LayoutInflater.from(mContext); - mClose = (NineLinearLayout)inflater.inflate(R.layout.abs__action_mode_close_item, this, false); - addView(mClose); - } else if (mClose.getParent() == null) { - addView(mClose); - } - - View closeButton = mClose.findViewById(R.id.abs__action_mode_close_button); - closeButton.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - mode.finish(); - } - }); - - final MenuBuilder menu = (MenuBuilder) mode.getMenu(); - if (mActionMenuPresenter != null) { - mActionMenuPresenter.dismissPopupMenus(); - } - mActionMenuPresenter = new ActionMenuPresenter(mContext); - mActionMenuPresenter.setReserveOverflow(true); - - final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.MATCH_PARENT); - if (!mSplitActionBar) { - menu.addMenuPresenter(mActionMenuPresenter); - mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - mMenuView.setBackgroundDrawable(null); - addView(mMenuView, layoutParams); - } else { - // Allow full screen width in split mode. - mActionMenuPresenter.setWidthLimit( - getContext().getResources().getDisplayMetrics().widthPixels, true); - // No limit to the item count; use whatever will fit. - mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); - // Span the whole width - layoutParams.width = LayoutParams.MATCH_PARENT; - layoutParams.height = mContentHeight; - menu.addMenuPresenter(mActionMenuPresenter); - mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - mMenuView.setBackgroundDrawable(mSplitBackground); - mSplitView.addView(mMenuView, layoutParams); - } - - mAnimateInOnLayout = true; - } - - public void closeMode() { - if (mAnimationMode == ANIMATE_OUT) { - // Called again during close; just finish what we were doing. - return; - } - if (mClose == null) { - killMode(); - return; - } - - finishAnimation(); - mAnimationMode = ANIMATE_OUT; - mCurrentAnimation = makeOutAnimation(); - mCurrentAnimation.start(); - } - - private void finishAnimation() { - final Animator a = mCurrentAnimation; - if (a != null) { - mCurrentAnimation = null; - a.end(); - } - } - - public void killMode() { - finishAnimation(); - removeAllViews(); - if (mSplitView != null) { - mSplitView.removeView(mMenuView); - } - mCustomView = null; - mMenuView = null; - mAnimateInOnLayout = false; - } - - @Override - public boolean showOverflowMenu() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.showOverflowMenu(); - } - return false; - } - - @Override - public boolean hideOverflowMenu() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.hideOverflowMenu(); - } - return false; - } - - @Override - public boolean isOverflowMenuShowing() { - if (mActionMenuPresenter != null) { - return mActionMenuPresenter.isOverflowMenuShowing(); - } - return false; - } - - @Override - protected ViewGroup.LayoutParams generateDefaultLayoutParams() { - // Used by custom views if they don't supply layout params. Everything else - // added to an ActionBarContextView should have them already. - return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - } - - @Override - public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { - return new MarginLayoutParams(getContext(), attrs); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + - "with android:layout_width=\"match_parent\" (or fill_parent)"); - } - - final int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightMode == MeasureSpec.UNSPECIFIED) { - throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + - "with android:layout_height=\"wrap_content\""); - } - - final int contentWidth = MeasureSpec.getSize(widthMeasureSpec); - - int maxHeight = mContentHeight > 0 ? - mContentHeight : MeasureSpec.getSize(heightMeasureSpec); - - final int verticalPadding = getPaddingTop() + getPaddingBottom(); - int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight(); - final int height = maxHeight - verticalPadding; - final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); - - if (mClose != null) { - availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0); - MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams(); - availableWidth -= lp.leftMargin + lp.rightMargin; - } - - if (mMenuView != null && mMenuView.getParent() == this) { - availableWidth = measureChildView(mMenuView, availableWidth, - childSpecHeight, 0); - } - - if (mTitleLayout != null && mCustomView == null) { - availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0); - } - - if (mCustomView != null) { - ViewGroup.LayoutParams lp = mCustomView.getLayoutParams(); - final int customWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? - MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; - final int customWidth = lp.width >= 0 ? - Math.min(lp.width, availableWidth) : availableWidth; - final int customHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? - MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; - final int customHeight = lp.height >= 0 ? - Math.min(lp.height, height) : height; - mCustomView.measure(MeasureSpec.makeMeasureSpec(customWidth, customWidthMode), - MeasureSpec.makeMeasureSpec(customHeight, customHeightMode)); - } - - if (mContentHeight <= 0) { - int measuredHeight = 0; - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - View v = getChildAt(i); - int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; - if (paddedViewHeight > measuredHeight) { - measuredHeight = paddedViewHeight; - } - } - setMeasuredDimension(contentWidth, measuredHeight); - } else { - setMeasuredDimension(contentWidth, maxHeight); - } - } - - private Animator makeInAnimation() { - mClose.setTranslationX(-mClose.getWidth() - - ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin); - ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", 0); - buttonAnimator.setDuration(200); - buttonAnimator.addListener(this); - buttonAnimator.setInterpolator(new DecelerateInterpolator()); - - AnimatorSet set = new AnimatorSet(); - AnimatorSet.Builder b = set.play(buttonAnimator); - - if (mMenuView != null) { - final int count = mMenuView.getChildCount(); - if (count > 0) { - for (int i = count - 1, j = 0; i >= 0; i--, j++) { - AnimatorProxy child = AnimatorProxy.wrap(mMenuView.getChildAt(i)); - child.setScaleY(0); - ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0, 1); - a.setDuration(100); - a.setStartDelay(j * 70); - b.with(a); - } - } - } - - return set; - } - - private Animator makeOutAnimation() { - ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", - -mClose.getWidth() - ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin); - buttonAnimator.setDuration(200); - buttonAnimator.addListener(this); - buttonAnimator.setInterpolator(new DecelerateInterpolator()); - - AnimatorSet set = new AnimatorSet(); - AnimatorSet.Builder b = set.play(buttonAnimator); - - if (mMenuView != null) { - final int count = mMenuView.getChildCount(); - if (count > 0) { - for (int i = 0; i < 0; i++) { - AnimatorProxy child = AnimatorProxy.wrap(mMenuView.getChildAt(i)); - child.setScaleY(0); - ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0); - a.setDuration(100); - a.setStartDelay(i * 70); - b.with(a); - } - } - } - - return set; - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int x = getPaddingLeft(); - final int y = getPaddingTop(); - final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); - - if (mClose != null && mClose.getVisibility() != GONE) { - MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams(); - x += lp.leftMargin; - x += positionChild(mClose, x, y, contentHeight); - x += lp.rightMargin; - - if (mAnimateInOnLayout) { - mAnimationMode = ANIMATE_IN; - mCurrentAnimation = makeInAnimation(); - mCurrentAnimation.start(); - mAnimateInOnLayout = false; - } - } - - if (mTitleLayout != null && mCustomView == null) { - x += positionChild(mTitleLayout, x, y, contentHeight); - } - - if (mCustomView != null) { - x += positionChild(mCustomView, x, y, contentHeight); - } - - x = r - l - getPaddingRight(); - - if (mMenuView != null) { - x -= positionChildInverse(mMenuView, x, y, contentHeight); - } - } - - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - if (mAnimationMode == ANIMATE_OUT) { - killMode(); - } - mAnimationMode = ANIMATE_IDLE; - } - - @Override - public void onAnimationCancel(Animator animation) { - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } - - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { - // Action mode started - //TODO event.setSource(this); - event.setClassName(getClass().getName()); - event.setPackageName(getContext().getPackageName()); - event.setContentDescription(mTitle); - } else { - //TODO super.onInitializeAccessibilityEvent(event); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java deleted file mode 100644 index 4636de17f..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java +++ /dev/null @@ -1,1548 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.widget; - -import org.xmlpull.v1.XmlPullParser; -import android.app.Activity; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.AssetManager; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.view.accessibility.AccessibilityEvent; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.SpinnerAdapter; -import android.widget.TextView; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.app.ActionBar.OnNavigationListener; -import com.actionbarsherlock.internal.ActionBarSherlockCompat; -import com.actionbarsherlock.internal.view.menu.ActionMenuItem; -import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; -import com.actionbarsherlock.internal.view.menu.ActionMenuView; -import com.actionbarsherlock.internal.view.menu.MenuBuilder; -import com.actionbarsherlock.internal.view.menu.MenuItemImpl; -import com.actionbarsherlock.internal.view.menu.MenuPresenter; -import com.actionbarsherlock.internal.view.menu.MenuView; -import com.actionbarsherlock.internal.view.menu.SubMenuBuilder; -import com.actionbarsherlock.view.CollapsibleActionView; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.Window; - -import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; - -/** - * @hide - */ -public class ActionBarView extends AbsActionBarView { - private static final String TAG = "ActionBarView"; - private static final boolean DEBUG = false; - - /** - * Display options applied by default - */ - public static final int DISPLAY_DEFAULT = 0; - - /** - * Display options that require re-layout as opposed to a simple invalidate - */ - private static final int DISPLAY_RELAYOUT_MASK = - ActionBar.DISPLAY_SHOW_HOME | - ActionBar.DISPLAY_USE_LOGO | - ActionBar.DISPLAY_HOME_AS_UP | - ActionBar.DISPLAY_SHOW_CUSTOM | - ActionBar.DISPLAY_SHOW_TITLE; - - private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL; - - private int mNavigationMode; - private int mDisplayOptions = -1; - private CharSequence mTitle; - private CharSequence mSubtitle; - private Drawable mIcon; - private Drawable mLogo; - - private HomeView mHomeLayout; - private HomeView mExpandedHomeLayout; - private LinearLayout mTitleLayout; - private TextView mTitleView; - private TextView mSubtitleView; - private View mTitleUpView; - - private IcsSpinner mSpinner; - private IcsLinearLayout mListNavLayout; - private ScrollingTabContainerView mTabScrollView; - private View mCustomNavView; - private IcsProgressBar mProgressView; - private IcsProgressBar mIndeterminateProgressView; - - private int mProgressBarPadding; - private int mItemPadding; - - private int mTitleStyleRes; - private int mSubtitleStyleRes; - private int mProgressStyle; - private int mIndeterminateProgressStyle; - - private boolean mUserTitle; - private boolean mIncludeTabs; - private boolean mIsCollapsable; - private boolean mIsCollapsed; - - private MenuBuilder mOptionsMenu; - - private ActionBarContextView mContextView; - - private ActionMenuItem mLogoNavItem; - - private SpinnerAdapter mSpinnerAdapter; - private OnNavigationListener mCallback; - - //UNUSED private Runnable mTabSelector; - - private ExpandedActionViewMenuPresenter mExpandedMenuPresenter; - View mExpandedActionView; - - Window.Callback mWindowCallback; - - @SuppressWarnings("rawtypes") - private final IcsAdapterView.OnItemSelectedListener mNavItemSelectedListener = - new IcsAdapterView.OnItemSelectedListener() { - public void onItemSelected(IcsAdapterView parent, View view, int position, long id) { - if (mCallback != null) { - mCallback.onNavigationItemSelected(position, id); - } - } - public void onNothingSelected(IcsAdapterView parent) { - // Do nothing - } - }; - - private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() { - @Override - public void onClick(View v) { - final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem; - if (item != null) { - item.collapseActionView(); - } - } - }; - - private final OnClickListener mUpClickListener = new OnClickListener() { - public void onClick(View v) { - mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem); - } - }; - - public ActionBarView(Context context, AttributeSet attrs) { - super(context, attrs); - - // Background is always provided by the container. - setBackgroundResource(0); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockActionBar, - R.attr.actionBarStyle, 0); - - ApplicationInfo appInfo = context.getApplicationInfo(); - PackageManager pm = context.getPackageManager(); - mNavigationMode = a.getInt(R.styleable.SherlockActionBar_navigationMode, - ActionBar.NAVIGATION_MODE_STANDARD); - mTitle = a.getText(R.styleable.SherlockActionBar_title); - mSubtitle = a.getText(R.styleable.SherlockActionBar_subtitle); - - mLogo = a.getDrawable(R.styleable.SherlockActionBar_logo); - if (mLogo == null) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - if (context instanceof Activity) { - //Even though native methods existed in API 9 and 10 they don't work - //so just parse the manifest to look for the logo pre-Honeycomb - final int resId = loadLogoFromManifest((Activity) context); - if (resId != 0) { - mLogo = context.getResources().getDrawable(resId); - } - } - } else { - if (context instanceof Activity) { - try { - mLogo = pm.getActivityLogo(((Activity) context).getComponentName()); - } catch (NameNotFoundException e) { - Log.e(TAG, "Activity component name not found!", e); - } - } - if (mLogo == null) { - mLogo = appInfo.loadLogo(pm); - } - } - } - - mIcon = a.getDrawable(R.styleable.SherlockActionBar_icon); - if (mIcon == null) { - if (context instanceof Activity) { - try { - mIcon = pm.getActivityIcon(((Activity) context).getComponentName()); - } catch (NameNotFoundException e) { - Log.e(TAG, "Activity component name not found!", e); - } - } - if (mIcon == null) { - mIcon = appInfo.loadIcon(pm); - } - } - - final LayoutInflater inflater = LayoutInflater.from(context); - - final int homeResId = a.getResourceId( - R.styleable.SherlockActionBar_homeLayout, - R.layout.abs__action_bar_home); - - mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false); - - mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false); - mExpandedHomeLayout.setUp(true); - mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener); - mExpandedHomeLayout.setContentDescription(getResources().getText( - R.string.abs__action_bar_up_description)); - - mTitleStyleRes = a.getResourceId(R.styleable.SherlockActionBar_titleTextStyle, 0); - mSubtitleStyleRes = a.getResourceId(R.styleable.SherlockActionBar_subtitleTextStyle, 0); - mProgressStyle = a.getResourceId(R.styleable.SherlockActionBar_progressBarStyle, 0); - mIndeterminateProgressStyle = a.getResourceId( - R.styleable.SherlockActionBar_indeterminateProgressStyle, 0); - - mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.SherlockActionBar_progressBarPadding, 0); - mItemPadding = a.getDimensionPixelOffset(R.styleable.SherlockActionBar_itemPadding, 0); - - setDisplayOptions(a.getInt(R.styleable.SherlockActionBar_displayOptions, DISPLAY_DEFAULT)); - - final int customNavId = a.getResourceId(R.styleable.SherlockActionBar_customNavigationLayout, 0); - if (customNavId != 0) { - mCustomNavView = inflater.inflate(customNavId, this, false); - mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD; - setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM); - } - - mContentHeight = a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0); - - a.recycle(); - - mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle); - mHomeLayout.setOnClickListener(mUpClickListener); - mHomeLayout.setClickable(true); - mHomeLayout.setFocusable(true); - } - - /** - * Attempt to programmatically load the logo from the manifest file of an - * activity by using an XML pull parser. This should allow us to read the - * logo attribute regardless of the platform it is being run on. - * - * @param activity Activity instance. - * @return Logo resource ID. - */ - private static int loadLogoFromManifest(Activity activity) { - int logo = 0; - try { - final String thisPackage = activity.getClass().getName(); - if (DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage); - - final String packageName = activity.getApplicationInfo().packageName; - final AssetManager am = activity.createPackageContext(packageName, 0).getAssets(); - final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml"); - - int eventType = xml.getEventType(); - while (eventType != XmlPullParser.END_DOCUMENT) { - if (eventType == XmlPullParser.START_TAG) { - String name = xml.getName(); - - if ("application".equals(name)) { - //Check if the has the attribute - if (DEBUG) Log.d(TAG, "Got "); - - for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { - if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); - - if ("logo".equals(xml.getAttributeName(i))) { - logo = xml.getAttributeResourceValue(i, 0); - break; //out of for loop - } - } - } else if ("activity".equals(name)) { - //Check if the is us and has the attribute - if (DEBUG) Log.d(TAG, "Got "); - Integer activityLogo = null; - String activityPackage = null; - boolean isOurActivity = false; - - for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { - if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); - - //We need both uiOptions and name attributes - String attrName = xml.getAttributeName(i); - if ("logo".equals(attrName)) { - activityLogo = xml.getAttributeResourceValue(i, 0); - } else if ("name".equals(attrName)) { - activityPackage = ActionBarSherlockCompat.cleanActivityName(packageName, xml.getAttributeValue(i)); - if (!thisPackage.equals(activityPackage)) { - break; //on to the next - } - isOurActivity = true; - } - - //Make sure we have both attributes before processing - if ((activityLogo != null) && (activityPackage != null)) { - //Our activity, logo specified, override with our value - logo = activityLogo.intValue(); - } - } - if (isOurActivity) { - //If we matched our activity but it had no logo don't - //do any more processing of the manifest - break; - } - } - } - eventType = xml.nextToken(); - } - } catch (Exception e) { - e.printStackTrace(); - } - if (DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(logo)); - return logo; - } - - /* - * Must be public so we can dispatch pre-2.2 via ActionBarImpl. - */ - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - mTitleView = null; - mSubtitleView = null; - mTitleUpView = null; - if (mTitleLayout != null && mTitleLayout.getParent() == this) { - removeView(mTitleLayout); - } - mTitleLayout = null; - if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) { - initTitle(); - } - - if (mTabScrollView != null && mIncludeTabs) { - ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams(); - if (lp != null) { - lp.width = LayoutParams.WRAP_CONTENT; - lp.height = LayoutParams.MATCH_PARENT; - } - mTabScrollView.setAllowCollapse(true); - } - } - - /** - * Set the window callback used to invoke menu items; used for dispatching home button presses. - * @param cb Window callback to dispatch to - */ - public void setWindowCallback(Window.Callback cb) { - mWindowCallback = cb; - } - - @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); - //UNUSED removeCallbacks(mTabSelector); - if (mActionMenuPresenter != null) { - mActionMenuPresenter.hideOverflowMenu(); - mActionMenuPresenter.hideSubMenus(); - } - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } - - public void initProgress() { - mProgressView = new IcsProgressBar(mContext, null, 0, mProgressStyle); - mProgressView.setId(R.id.abs__progress_horizontal); - mProgressView.setMax(10000); - addView(mProgressView); - } - - public void initIndeterminateProgress() { - mIndeterminateProgressView = new IcsProgressBar(mContext, null, 0, mIndeterminateProgressStyle); - mIndeterminateProgressView.setId(R.id.abs__progress_circular); - addView(mIndeterminateProgressView); - } - - @Override - public void setSplitActionBar(boolean splitActionBar) { - if (mSplitActionBar != splitActionBar) { - if (mMenuView != null) { - final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); - if (oldParent != null) { - oldParent.removeView(mMenuView); - } - if (splitActionBar) { - if (mSplitView != null) { - mSplitView.addView(mMenuView); - } - } else { - addView(mMenuView); - } - } - if (mSplitView != null) { - mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE); - } - super.setSplitActionBar(splitActionBar); - } - } - - public boolean isSplitActionBar() { - return mSplitActionBar; - } - - public boolean hasEmbeddedTabs() { - return mIncludeTabs; - } - - public void setEmbeddedTabView(ScrollingTabContainerView tabs) { - if (mTabScrollView != null) { - removeView(mTabScrollView); - } - mTabScrollView = tabs; - mIncludeTabs = tabs != null; - if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) { - addView(mTabScrollView); - ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams(); - lp.width = LayoutParams.WRAP_CONTENT; - lp.height = LayoutParams.MATCH_PARENT; - tabs.setAllowCollapse(true); - } - } - - public void setCallback(OnNavigationListener callback) { - mCallback = callback; - } - - public void setMenu(Menu menu, MenuPresenter.Callback cb) { - if (menu == mOptionsMenu) return; - - if (mOptionsMenu != null) { - mOptionsMenu.removeMenuPresenter(mActionMenuPresenter); - mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter); - } - - MenuBuilder builder = (MenuBuilder) menu; - mOptionsMenu = builder; - if (mMenuView != null) { - final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); - if (oldParent != null) { - oldParent.removeView(mMenuView); - } - } - if (mActionMenuPresenter == null) { - mActionMenuPresenter = new ActionMenuPresenter(mContext); - mActionMenuPresenter.setCallback(cb); - mActionMenuPresenter.setId(R.id.abs__action_menu_presenter); - mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter(); - } - - ActionMenuView menuView; - final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.MATCH_PARENT); - if (!mSplitActionBar) { - mActionMenuPresenter.setExpandedActionViewsExclusive( - getResources_getBoolean(getContext(), - R.bool.abs__action_bar_expanded_action_views_exclusive)); - configPresenters(builder); - menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - final ViewGroup oldParent = (ViewGroup) menuView.getParent(); - if (oldParent != null && oldParent != this) { - oldParent.removeView(menuView); - } - addView(menuView, layoutParams); - } else { - mActionMenuPresenter.setExpandedActionViewsExclusive(false); - // Allow full screen width in split mode. - mActionMenuPresenter.setWidthLimit( - getContext().getResources().getDisplayMetrics().widthPixels, true); - // No limit to the item count; use whatever will fit. - mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); - // Span the whole width - layoutParams.width = LayoutParams.MATCH_PARENT; - configPresenters(builder); - menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); - if (mSplitView != null) { - final ViewGroup oldParent = (ViewGroup) menuView.getParent(); - if (oldParent != null && oldParent != mSplitView) { - oldParent.removeView(menuView); - } - menuView.setVisibility(getAnimatedVisibility()); - mSplitView.addView(menuView, layoutParams); - } else { - // We'll add this later if we missed it this time. - menuView.setLayoutParams(layoutParams); - } - } - mMenuView = menuView; - } - - private void configPresenters(MenuBuilder builder) { - if (builder != null) { - builder.addMenuPresenter(mActionMenuPresenter); - builder.addMenuPresenter(mExpandedMenuPresenter); - } else { - mActionMenuPresenter.initForMenu(mContext, null); - mExpandedMenuPresenter.initForMenu(mContext, null); - mActionMenuPresenter.updateMenuView(true); - mExpandedMenuPresenter.updateMenuView(true); - } - } - - public boolean hasExpandedActionView() { - return mExpandedMenuPresenter != null && - mExpandedMenuPresenter.mCurrentExpandedItem != null; - } - - public void collapseActionView() { - final MenuItemImpl item = mExpandedMenuPresenter == null ? null : - mExpandedMenuPresenter.mCurrentExpandedItem; - if (item != null) { - item.collapseActionView(); - } - } - - public void setCustomNavigationView(View view) { - final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0; - if (mCustomNavView != null && showCustom) { - removeView(mCustomNavView); - } - mCustomNavView = view; - if (mCustomNavView != null && showCustom) { - addView(mCustomNavView); - } - } - - public CharSequence getTitle() { - return mTitle; - } - - /** - * Set the action bar title. This will always replace or override window titles. - * @param title Title to set - * - * @see #setWindowTitle(CharSequence) - */ - public void setTitle(CharSequence title) { - mUserTitle = true; - setTitleImpl(title); - } - - /** - * Set the window title. A window title will always be replaced or overridden by a user title. - * @param title Title to set - * - * @see #setTitle(CharSequence) - */ - public void setWindowTitle(CharSequence title) { - if (!mUserTitle) { - setTitleImpl(title); - } - } - - private void setTitleImpl(CharSequence title) { - mTitle = title; - if (mTitleView != null) { - mTitleView.setText(title); - final boolean visible = mExpandedActionView == null && - (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 && - (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle)); - mTitleLayout.setVisibility(visible ? VISIBLE : GONE); - } - if (mLogoNavItem != null) { - mLogoNavItem.setTitle(title); - } - } - - public CharSequence getSubtitle() { - return mSubtitle; - } - - public void setSubtitle(CharSequence subtitle) { - mSubtitle = subtitle; - if (mSubtitleView != null) { - mSubtitleView.setText(subtitle); - mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE); - final boolean visible = mExpandedActionView == null && - (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 && - (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle)); - mTitleLayout.setVisibility(visible ? VISIBLE : GONE); - } - } - - public void setHomeButtonEnabled(boolean enable) { - mHomeLayout.setEnabled(enable); - mHomeLayout.setFocusable(enable); - // Make sure the home button has an accurate content description for accessibility. - if (!enable) { - mHomeLayout.setContentDescription(null); - } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) { - mHomeLayout.setContentDescription(mContext.getResources().getText( - R.string.abs__action_bar_up_description)); - } else { - mHomeLayout.setContentDescription(mContext.getResources().getText( - R.string.abs__action_bar_home_description)); - } - } - - public void setDisplayOptions(int options) { - final int flagsChanged = mDisplayOptions == -1 ? -1 : options ^ mDisplayOptions; - mDisplayOptions = options; - - if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) { - final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0; - final int vis = showHome && mExpandedActionView == null ? VISIBLE : GONE; - mHomeLayout.setVisibility(vis); - - if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) { - final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0; - mHomeLayout.setUp(setUp); - - // Showing home as up implicitly enables interaction with it. - // In honeycomb it was always enabled, so make this transition - // a bit easier for developers in the common case. - // (It would be silly to show it as up without responding to it.) - if (setUp) { - setHomeButtonEnabled(true); - } - } - - if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) { - final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0; - mHomeLayout.setIcon(logoVis ? mLogo : mIcon); - } - - if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) { - if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) { - initTitle(); - } else { - removeView(mTitleLayout); - } - } - - if (mTitleLayout != null && (flagsChanged & - (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) { - final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0; - mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE); - mTitleLayout.setEnabled(!showHome && homeAsUp); - } - - if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) { - if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { - addView(mCustomNavView); - } else { - removeView(mCustomNavView); - } - } - - requestLayout(); - } else { - invalidate(); - } - - // Make sure the home button has an accurate content description for accessibility. - if (!mHomeLayout.isEnabled()) { - mHomeLayout.setContentDescription(null); - } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) { - mHomeLayout.setContentDescription(mContext.getResources().getText( - R.string.abs__action_bar_up_description)); - } else { - mHomeLayout.setContentDescription(mContext.getResources().getText( - R.string.abs__action_bar_home_description)); - } - } - - public void setIcon(Drawable icon) { - mIcon = icon; - if (icon != null && - ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) { - mHomeLayout.setIcon(icon); - } - } - - public void setIcon(int resId) { - setIcon(mContext.getResources().getDrawable(resId)); - } - - public void setLogo(Drawable logo) { - mLogo = logo; - if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) { - mHomeLayout.setIcon(logo); - } - } - - public void setLogo(int resId) { - setLogo(mContext.getResources().getDrawable(resId)); - } - - public void setNavigationMode(int mode) { - final int oldMode = mNavigationMode; - if (mode != oldMode) { - switch (oldMode) { - case ActionBar.NAVIGATION_MODE_LIST: - if (mListNavLayout != null) { - removeView(mListNavLayout); - } - break; - case ActionBar.NAVIGATION_MODE_TABS: - if (mTabScrollView != null && mIncludeTabs) { - removeView(mTabScrollView); - } - } - - switch (mode) { - case ActionBar.NAVIGATION_MODE_LIST: - if (mSpinner == null) { - mSpinner = new IcsSpinner(mContext, null, - R.attr.actionDropDownStyle); - mListNavLayout = (IcsLinearLayout) LayoutInflater.from(mContext) - .inflate(R.layout.abs__action_bar_tab_bar_view, null); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); - params.gravity = Gravity.CENTER; - mListNavLayout.addView(mSpinner, params); - } - if (mSpinner.getAdapter() != mSpinnerAdapter) { - mSpinner.setAdapter(mSpinnerAdapter); - } - mSpinner.setOnItemSelectedListener(mNavItemSelectedListener); - addView(mListNavLayout); - break; - case ActionBar.NAVIGATION_MODE_TABS: - if (mTabScrollView != null && mIncludeTabs) { - addView(mTabScrollView); - } - break; - } - mNavigationMode = mode; - requestLayout(); - } - } - - public void setDropdownAdapter(SpinnerAdapter adapter) { - mSpinnerAdapter = adapter; - if (mSpinner != null) { - mSpinner.setAdapter(adapter); - } - } - - public SpinnerAdapter getDropdownAdapter() { - return mSpinnerAdapter; - } - - public void setDropdownSelectedPosition(int position) { - mSpinner.setSelection(position); - } - - public int getDropdownSelectedPosition() { - return mSpinner.getSelectedItemPosition(); - } - - public View getCustomNavigationView() { - return mCustomNavView; - } - - public int getNavigationMode() { - return mNavigationMode; - } - - public int getDisplayOptions() { - return mDisplayOptions; - } - - @Override - protected ViewGroup.LayoutParams generateDefaultLayoutParams() { - // Used by custom nav views if they don't supply layout params. Everything else - // added to an ActionBarView should have them already. - return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - addView(mHomeLayout); - - if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { - final ViewParent parent = mCustomNavView.getParent(); - if (parent != this) { - if (parent instanceof ViewGroup) { - ((ViewGroup) parent).removeView(mCustomNavView); - } - addView(mCustomNavView); - } - } - } - - private void initTitle() { - if (mTitleLayout == null) { - LayoutInflater inflater = LayoutInflater.from(getContext()); - mTitleLayout = (LinearLayout) inflater.inflate(R.layout.abs__action_bar_title_item, - this, false); - mTitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_title); - mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_subtitle); - mTitleUpView = mTitleLayout.findViewById(R.id.abs__up); - - mTitleLayout.setOnClickListener(mUpClickListener); - - if (mTitleStyleRes != 0) { - mTitleView.setTextAppearance(mContext, mTitleStyleRes); - } - if (mTitle != null) { - mTitleView.setText(mTitle); - } - - if (mSubtitleStyleRes != 0) { - mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); - } - if (mSubtitle != null) { - mSubtitleView.setText(mSubtitle); - mSubtitleView.setVisibility(VISIBLE); - } - - final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0; - final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0; - mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE); - mTitleLayout.setEnabled(homeAsUp && !showHome); - } - - addView(mTitleLayout); - if (mExpandedActionView != null || - (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) { - // Don't show while in expanded mode or with empty text - mTitleLayout.setVisibility(GONE); - } - } - - public void setContextView(ActionBarContextView view) { - mContextView = view; - } - - public void setCollapsable(boolean collapsable) { - mIsCollapsable = collapsable; - } - - public boolean isCollapsed() { - return mIsCollapsed; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int childCount = getChildCount(); - if (mIsCollapsable) { - int visibleChildren = 0; - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - if (child.getVisibility() != GONE && - !(child == mMenuView && mMenuView.getChildCount() == 0)) { - visibleChildren++; - } - } - - if (visibleChildren == 0) { - // No size for an empty action bar when collapsable. - setMeasuredDimension(0, 0); - mIsCollapsed = true; - return; - } - } - mIsCollapsed = false; - - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + - "with android:layout_width=\"match_parent\" (or fill_parent)"); - } - - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightMode != MeasureSpec.AT_MOST) { - throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + - "with android:layout_height=\"wrap_content\""); - } - - int contentWidth = MeasureSpec.getSize(widthMeasureSpec); - - int maxHeight = mContentHeight > 0 ? - mContentHeight : MeasureSpec.getSize(heightMeasureSpec); - - final int verticalPadding = getPaddingTop() + getPaddingBottom(); - final int paddingLeft = getPaddingLeft(); - final int paddingRight = getPaddingRight(); - final int height = maxHeight - verticalPadding; - final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); - - int availableWidth = contentWidth - paddingLeft - paddingRight; - int leftOfCenter = availableWidth / 2; - int rightOfCenter = leftOfCenter; - - HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; - - if (homeLayout.getVisibility() != GONE) { - final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams(); - int homeWidthSpec; - if (lp.width < 0) { - homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST); - } else { - homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); - } - homeLayout.measure(homeWidthSpec, - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); - final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset(); - availableWidth = Math.max(0, availableWidth - homeWidth); - leftOfCenter = Math.max(0, availableWidth - homeWidth); - } - - if (mMenuView != null && mMenuView.getParent() == this) { - availableWidth = measureChildView(mMenuView, availableWidth, - childSpecHeight, 0); - rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth()); - } - - if (mIndeterminateProgressView != null && - mIndeterminateProgressView.getVisibility() != GONE) { - availableWidth = measureChildView(mIndeterminateProgressView, availableWidth, - childSpecHeight, 0); - rightOfCenter = Math.max(0, - rightOfCenter - mIndeterminateProgressView.getMeasuredWidth()); - } - - final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && - (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; - - if (mExpandedActionView == null) { - switch (mNavigationMode) { - case ActionBar.NAVIGATION_MODE_LIST: - if (mListNavLayout != null) { - final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; - availableWidth = Math.max(0, availableWidth - itemPaddingSize); - leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); - mListNavLayout.measure( - MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); - final int listNavWidth = mListNavLayout.getMeasuredWidth(); - availableWidth = Math.max(0, availableWidth - listNavWidth); - leftOfCenter = Math.max(0, leftOfCenter - listNavWidth); - } - break; - case ActionBar.NAVIGATION_MODE_TABS: - if (mTabScrollView != null) { - final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; - availableWidth = Math.max(0, availableWidth - itemPaddingSize); - leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); - mTabScrollView.measure( - MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); - final int tabWidth = mTabScrollView.getMeasuredWidth(); - availableWidth = Math.max(0, availableWidth - tabWidth); - leftOfCenter = Math.max(0, leftOfCenter - tabWidth); - } - break; - } - } - - View customView = null; - if (mExpandedActionView != null) { - customView = mExpandedActionView; - } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && - mCustomNavView != null) { - customView = mCustomNavView; - } - - if (customView != null) { - final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams()); - final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? - (ActionBar.LayoutParams) lp : null; - - int horizontalMargin = 0; - int verticalMargin = 0; - if (ablp != null) { - horizontalMargin = ablp.leftMargin + ablp.rightMargin; - verticalMargin = ablp.topMargin + ablp.bottomMargin; - } - - // If the action bar is wrapping to its content height, don't allow a custom - // view to MATCH_PARENT. - int customNavHeightMode; - if (mContentHeight <= 0) { - customNavHeightMode = MeasureSpec.AT_MOST; - } else { - customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? - MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; - } - final int customNavHeight = Math.max(0, - (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin); - - final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? - MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; - int customNavWidth = Math.max(0, - (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth) - - horizontalMargin); - final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) & - Gravity.HORIZONTAL_GRAVITY_MASK; - - // Centering a custom view is treated specially; we try to center within the whole - // action bar rather than in the available space. - if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) { - customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2; - } - - customView.measure( - MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode), - MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode)); - availableWidth -= horizontalMargin + customView.getMeasuredWidth(); - } - - if (mExpandedActionView == null && showTitle) { - availableWidth = measureChildView(mTitleLayout, availableWidth, - MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0); - leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth()); - } - - if (mContentHeight <= 0) { - int measuredHeight = 0; - for (int i = 0; i < childCount; i++) { - View v = getChildAt(i); - int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; - if (paddedViewHeight > measuredHeight) { - measuredHeight = paddedViewHeight; - } - } - setMeasuredDimension(contentWidth, measuredHeight); - } else { - setMeasuredDimension(contentWidth, maxHeight); - } - - if (mContextView != null) { - mContextView.setContentHeight(getMeasuredHeight()); - } - - if (mProgressView != null && mProgressView.getVisibility() != GONE) { - mProgressView.measure(MeasureSpec.makeMeasureSpec( - contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); - } - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int x = getPaddingLeft(); - final int y = getPaddingTop(); - final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); - - if (contentHeight <= 0) { - // Nothing to do if we can't see anything. - return; - } - - HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; - if (homeLayout.getVisibility() != GONE) { - final int leftOffset = homeLayout.getLeftOffset(); - x += positionChild(homeLayout, x + leftOffset, y, contentHeight) + leftOffset; - } - - if (mExpandedActionView == null) { - final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && - (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; - if (showTitle) { - x += positionChild(mTitleLayout, x, y, contentHeight); - } - - switch (mNavigationMode) { - case ActionBar.NAVIGATION_MODE_STANDARD: - break; - case ActionBar.NAVIGATION_MODE_LIST: - if (mListNavLayout != null) { - if (showTitle) x += mItemPadding; - x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding; - } - break; - case ActionBar.NAVIGATION_MODE_TABS: - if (mTabScrollView != null) { - if (showTitle) x += mItemPadding; - x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding; - } - break; - } - } - - int menuLeft = r - l - getPaddingRight(); - if (mMenuView != null && mMenuView.getParent() == this) { - positionChildInverse(mMenuView, menuLeft, y, contentHeight); - menuLeft -= mMenuView.getMeasuredWidth(); - } - - if (mIndeterminateProgressView != null && - mIndeterminateProgressView.getVisibility() != GONE) { - positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight); - menuLeft -= mIndeterminateProgressView.getMeasuredWidth(); - } - - View customView = null; - if (mExpandedActionView != null) { - customView = mExpandedActionView; - } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && - mCustomNavView != null) { - customView = mCustomNavView; - } - if (customView != null) { - ViewGroup.LayoutParams lp = customView.getLayoutParams(); - final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? - (ActionBar.LayoutParams) lp : null; - - final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY; - final int navWidth = customView.getMeasuredWidth(); - - int topMargin = 0; - int bottomMargin = 0; - if (ablp != null) { - x += ablp.leftMargin; - menuLeft -= ablp.rightMargin; - topMargin = ablp.topMargin; - bottomMargin = ablp.bottomMargin; - } - - int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; - // See if we actually have room to truly center; if not push against left or right. - if (hgravity == Gravity.CENTER_HORIZONTAL) { - final int centeredLeft = ((getRight() - getLeft()) - navWidth) / 2; - if (centeredLeft < x) { - hgravity = Gravity.LEFT; - } else if (centeredLeft + navWidth > menuLeft) { - hgravity = Gravity.RIGHT; - } - } else if (gravity == -1) { - hgravity = Gravity.LEFT; - } - - int xpos = 0; - switch (hgravity) { - case Gravity.CENTER_HORIZONTAL: - xpos = ((getRight() - getLeft()) - navWidth) / 2; - break; - case Gravity.LEFT: - xpos = x; - break; - case Gravity.RIGHT: - xpos = menuLeft - navWidth; - break; - } - - int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; - - if (gravity == -1) { - vgravity = Gravity.CENTER_VERTICAL; - } - - int ypos = 0; - switch (vgravity) { - case Gravity.CENTER_VERTICAL: - final int paddedTop = getPaddingTop(); - final int paddedBottom = getBottom() - getTop() - getPaddingBottom(); - ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2; - break; - case Gravity.TOP: - ypos = getPaddingTop() + topMargin; - break; - case Gravity.BOTTOM: - ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight() - - bottomMargin; - break; - } - final int customWidth = customView.getMeasuredWidth(); - customView.layout(xpos, ypos, xpos + customWidth, - ypos + customView.getMeasuredHeight()); - x += customWidth; - } - - if (mProgressView != null) { - mProgressView.bringToFront(); - final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2; - mProgressView.layout(mProgressBarPadding, -halfProgressHeight, - mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight); - } - } - - @Override - public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { - return new ActionBar.LayoutParams(getContext(), attrs); - } - - @Override - public ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - if (lp == null) { - lp = generateDefaultLayoutParams(); - } - return lp; - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - SavedState state = new SavedState(superState); - - if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) { - state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId(); - } - - state.isOverflowOpen = isOverflowMenuShowing(); - - return state; - } - - @Override - public void onRestoreInstanceState(Parcelable p) { - SavedState state = (SavedState) p; - - super.onRestoreInstanceState(state.getSuperState()); - - if (state.expandedMenuItemId != 0 && - mExpandedMenuPresenter != null && mOptionsMenu != null) { - final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId); - if (item != null) { - item.expandActionView(); - } - } - - if (state.isOverflowOpen) { - postShowOverflowMenu(); - } - } - - static class SavedState extends BaseSavedState { - int expandedMenuItemId; - boolean isOverflowOpen; - - SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - expandedMenuItemId = in.readInt(); - isOverflowOpen = in.readInt() != 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeInt(expandedMenuItemId); - out.writeInt(isOverflowOpen ? 1 : 0); - } - - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - public static class HomeView extends FrameLayout { - private View mUpView; - private ImageView mIconView; - private int mUpWidth; - - public HomeView(Context context) { - this(context, null); - } - - public HomeView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void setUp(boolean isUp) { - mUpView.setVisibility(isUp ? VISIBLE : GONE); - } - - public void setIcon(Drawable icon) { - mIconView.setImageDrawable(icon); - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - onPopulateAccessibilityEvent(event); - return true; - } - - @Override - public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - super.onPopulateAccessibilityEvent(event); - } - final CharSequence cdesc = getContentDescription(); - if (!TextUtils.isEmpty(cdesc)) { - event.getText().add(cdesc); - } - } - - @Override - public boolean dispatchHoverEvent(MotionEvent event) { - // Don't allow children to hover; we want this to be treated as a single component. - return onHoverEvent(event); - } - - @Override - protected void onFinishInflate() { - mUpView = findViewById(R.id.abs__up); - mIconView = (ImageView) findViewById(R.id.abs__home); - } - - public int getLeftOffset() { - return mUpView.getVisibility() == GONE ? mUpWidth : 0; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0); - final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); - mUpWidth = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin; - int width = mUpView.getVisibility() == GONE ? 0 : mUpWidth; - int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin; - measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0); - final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); - width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin; - height = Math.max(height, - iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin); - - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - final int heightMode = MeasureSpec.getMode(heightMeasureSpec); - final int widthSize = MeasureSpec.getSize(widthMeasureSpec); - final int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - switch (widthMode) { - case MeasureSpec.AT_MOST: - width = Math.min(width, widthSize); - break; - case MeasureSpec.EXACTLY: - width = widthSize; - break; - case MeasureSpec.UNSPECIFIED: - default: - break; - } - switch (heightMode) { - case MeasureSpec.AT_MOST: - height = Math.min(height, heightSize); - break; - case MeasureSpec.EXACTLY: - height = heightSize; - break; - case MeasureSpec.UNSPECIFIED: - default: - break; - } - setMeasuredDimension(width, height); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - final int vCenter = (b - t) / 2; - //UNUSED int width = r - l; - int upOffset = 0; - if (mUpView.getVisibility() != GONE) { - final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); - final int upHeight = mUpView.getMeasuredHeight(); - final int upWidth = mUpView.getMeasuredWidth(); - final int upTop = vCenter - upHeight / 2; - mUpView.layout(0, upTop, upWidth, upTop + upHeight); - upOffset = upLp.leftMargin + upWidth + upLp.rightMargin; - //UNUSED width -= upOffset; - l += upOffset; - } - final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); - final int iconHeight = mIconView.getMeasuredHeight(); - final int iconWidth = mIconView.getMeasuredWidth(); - final int hCenter = (r - l) / 2; - final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2); - final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2); - mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight); - } - } - - private class ExpandedActionViewMenuPresenter implements MenuPresenter { - MenuBuilder mMenu; - MenuItemImpl mCurrentExpandedItem; - - @Override - public void initForMenu(Context context, MenuBuilder menu) { - // Clear the expanded action view when menus change. - if (mMenu != null && mCurrentExpandedItem != null) { - mMenu.collapseItemActionView(mCurrentExpandedItem); - } - mMenu = menu; - } - - @Override - public MenuView getMenuView(ViewGroup root) { - return null; - } - - @Override - public void updateMenuView(boolean cleared) { - // Make sure the expanded item we have is still there. - if (mCurrentExpandedItem != null) { - boolean found = false; - - if (mMenu != null) { - final int count = mMenu.size(); - for (int i = 0; i < count; i++) { - final MenuItem item = mMenu.getItem(i); - if (item == mCurrentExpandedItem) { - found = true; - break; - } - } - } - - if (!found) { - // The item we had expanded disappeared. Collapse. - collapseItemActionView(mMenu, mCurrentExpandedItem); - } - } - } - - @Override - public void setCallback(Callback cb) { - } - - @Override - public boolean onSubMenuSelected(SubMenuBuilder subMenu) { - return false; - } - - @Override - public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { - } - - @Override - public boolean flagActionItems() { - return false; - } - - @Override - public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { - mExpandedActionView = item.getActionView(); - mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(/* TODO getResources() */)); - mCurrentExpandedItem = item; - if (mExpandedActionView.getParent() != ActionBarView.this) { - addView(mExpandedActionView); - } - if (mExpandedHomeLayout.getParent() != ActionBarView.this) { - addView(mExpandedHomeLayout); - } - mHomeLayout.setVisibility(GONE); - if (mTitleLayout != null) mTitleLayout.setVisibility(GONE); - if (mTabScrollView != null) mTabScrollView.setVisibility(GONE); - if (mSpinner != null) mSpinner.setVisibility(GONE); - if (mCustomNavView != null) mCustomNavView.setVisibility(GONE); - requestLayout(); - item.setActionViewExpanded(true); - - if (mExpandedActionView instanceof CollapsibleActionView) { - ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded(); - } - - return true; - } - - @Override - public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { - // Do this before detaching the actionview from the hierarchy, in case - // it needs to dismiss the soft keyboard, etc. - if (mExpandedActionView instanceof CollapsibleActionView) { - ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed(); - } - - removeView(mExpandedActionView); - removeView(mExpandedHomeLayout); - mExpandedActionView = null; - if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) { - mHomeLayout.setVisibility(VISIBLE); - } - if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) { - if (mTitleLayout == null) { - initTitle(); - } else { - mTitleLayout.setVisibility(VISIBLE); - } - } - if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) { - mTabScrollView.setVisibility(VISIBLE); - } - if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) { - mSpinner.setVisibility(VISIBLE); - } - if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { - mCustomNavView.setVisibility(VISIBLE); - } - mExpandedHomeLayout.setIcon(null); - mCurrentExpandedItem = null; - requestLayout(); - item.setActionViewExpanded(false); - - return true; - } - - @Override - public int getId() { - return 0; - } - - @Override - public Parcelable onSaveInstanceState() { - return null; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java deleted file mode 100644 index fa3698f3b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import java.util.Locale; -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Build; -import android.util.AttributeSet; -import android.widget.Button; - -public class CapitalizingButton extends Button { - private static final boolean SANS_ICE_CREAM = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH; - private static final boolean IS_GINGERBREAD = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; - - private static final int[] R_styleable_Button = new int[] { - android.R.attr.textAllCaps - }; - private static final int R_styleable_Button_textAllCaps = 0; - - private boolean mAllCaps; - - public CapitalizingButton(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, R_styleable_Button); - mAllCaps = a.getBoolean(R_styleable_Button_textAllCaps, true); - a.recycle(); - } - - public void setTextCompat(CharSequence text) { - if (SANS_ICE_CREAM && mAllCaps && text != null) { - if (IS_GINGERBREAD) { - setText(text.toString().toUpperCase(Locale.ROOT)); - } else { - setText(text.toString().toUpperCase()); - } - } else { - setText(text); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java deleted file mode 100644 index cae8b8aed..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Build; -import android.util.AttributeSet; -import android.widget.TextView; - -import java.util.Locale; - -public class CapitalizingTextView extends TextView { - private static final boolean SANS_ICE_CREAM = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH; - private static final boolean IS_GINGERBREAD = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; - - private static final int[] R_styleable_TextView = new int[] { - android.R.attr.textAllCaps - }; - private static final int R_styleable_TextView_textAllCaps = 0; - - private boolean mAllCaps; - - public CapitalizingTextView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public CapitalizingTextView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - TypedArray a = context.obtainStyledAttributes(attrs, R_styleable_TextView, defStyle, 0); - mAllCaps = a.getBoolean(R_styleable_TextView_textAllCaps, true); - a.recycle(); - } - - public void setTextCompat(CharSequence text) { - if (SANS_ICE_CREAM && mAllCaps && text != null) { - if (IS_GINGERBREAD) { - try { - setText(text.toString().toUpperCase(Locale.ROOT)); - } catch (NoSuchFieldError e) { - //Some manufacturer broke Locale.ROOT. See #572. - setText(text.toString().toUpperCase()); - } - } else { - setText(text.toString().toUpperCase()); - } - } else { - setText(text); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java deleted file mode 100644 index 14f092c81..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import android.view.View; -import android.widget.FrameLayout; -import com.actionbarsherlock.view.CollapsibleActionView; - -/** - * Wraps an ABS collapsible action view in a native container that delegates the calls. - */ -public class CollapsibleActionViewWrapper extends FrameLayout implements android.view.CollapsibleActionView { - private final CollapsibleActionView child; - - public CollapsibleActionViewWrapper(View child) { - super(child.getContext()); - this.child = (CollapsibleActionView) child; - addView(child); - } - - @Override public void onActionViewExpanded() { - child.onActionViewExpanded(); - } - - @Override public void onActionViewCollapsed() { - child.onActionViewCollapsed(); - } - - public View unwrap() { - return getChildAt(0); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java deleted file mode 100644 index ad1b4f0a8..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import static android.view.View.MeasureSpec.EXACTLY; -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.TypedValue; -import android.widget.LinearLayout; -import com.actionbarsherlock.R; - -public class FakeDialogPhoneWindow extends LinearLayout { - final TypedValue mMinWidthMajor = new TypedValue(); - final TypedValue mMinWidthMinor = new TypedValue(); - - public FakeDialogPhoneWindow(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockTheme); - - a.getValue(R.styleable.SherlockTheme_windowMinWidthMajor, mMinWidthMajor); - a.getValue(R.styleable.SherlockTheme_windowMinWidthMinor, mMinWidthMinor); - - a.recycle(); - } - - /* Stolen from PhoneWindow */ - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); - final boolean isPortrait = metrics.widthPixels < metrics.heightPixels; - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - int width = getMeasuredWidth(); - boolean measure = false; - - widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY); - - final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor; - - if (tv.type != TypedValue.TYPE_NULL) { - final int min; - if (tv.type == TypedValue.TYPE_DIMENSION) { - min = (int)tv.getDimension(metrics); - } else if (tv.type == TypedValue.TYPE_FRACTION) { - min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels); - } else { - min = 0; - } - - if (width < min) { - widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY); - measure = true; - } - } - - // TODO: Support height? - - if (measure) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java deleted file mode 100644 index ce0cb3bca..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.database.DataSetObserver; -import android.graphics.Rect; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.util.AttributeSet; -import android.util.SparseArray; -import android.view.View; -import android.view.ViewGroup; -import android.widget.SpinnerAdapter; - -/** - * An abstract base class for spinner widgets. SDK users will probably not - * need to use this class. - * - * @attr ref android.R.styleable#AbsSpinner_entries - */ -public abstract class IcsAbsSpinner extends IcsAdapterView { - private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; - - SpinnerAdapter mAdapter; - - int mHeightMeasureSpec; - int mWidthMeasureSpec; - boolean mBlockLayoutRequests; - - int mSelectionLeftPadding = 0; - int mSelectionTopPadding = 0; - int mSelectionRightPadding = 0; - int mSelectionBottomPadding = 0; - final Rect mSpinnerPadding = new Rect(); - - final RecycleBin mRecycler = new RecycleBin(); - private DataSetObserver mDataSetObserver; - - /** Temporary frame to hold a child View's frame rectangle */ - private Rect mTouchFrame; - - public IcsAbsSpinner(Context context) { - super(context); - initAbsSpinner(); - } - - public IcsAbsSpinner(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public IcsAbsSpinner(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initAbsSpinner(); - - /* - TypedArray a = context.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.AbsSpinner, defStyle, 0); - - CharSequence[] entries = a.getTextArray(R.styleable.AbsSpinner_entries); - if (entries != null) { - ArrayAdapter adapter = - new ArrayAdapter(context, - R.layout.simple_spinner_item, entries); - adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); - setAdapter(adapter); - } - - a.recycle(); - */ - } - - /** - * Common code for different constructor flavors - */ - private void initAbsSpinner() { - setFocusable(true); - setWillNotDraw(false); - } - - /** - * The Adapter is used to provide the data which backs this Spinner. - * It also provides methods to transform spinner items based on their position - * relative to the selected item. - * @param adapter The SpinnerAdapter to use for this Spinner - */ - @Override - public void setAdapter(SpinnerAdapter adapter) { - if (null != mAdapter) { - mAdapter.unregisterDataSetObserver(mDataSetObserver); - resetList(); - } - - mAdapter = adapter; - - mOldSelectedPosition = INVALID_POSITION; - mOldSelectedRowId = INVALID_ROW_ID; - - if (mAdapter != null) { - mOldItemCount = mItemCount; - mItemCount = mAdapter.getCount(); - checkFocus(); - - mDataSetObserver = new AdapterDataSetObserver(); - mAdapter.registerDataSetObserver(mDataSetObserver); - - int position = mItemCount > 0 ? 0 : INVALID_POSITION; - - setSelectedPositionInt(position); - setNextSelectedPositionInt(position); - - if (mItemCount == 0) { - // Nothing selected - checkSelectionChanged(); - } - - } else { - checkFocus(); - resetList(); - // Nothing selected - checkSelectionChanged(); - } - - requestLayout(); - } - - /** - * Clear out all children from the list - */ - void resetList() { - mDataChanged = false; - mNeedSync = false; - - removeAllViewsInLayout(); - mOldSelectedPosition = INVALID_POSITION; - mOldSelectedRowId = INVALID_ROW_ID; - - setSelectedPositionInt(INVALID_POSITION); - setNextSelectedPositionInt(INVALID_POSITION); - invalidate(); - } - - /** - * @see android.view.View#measure(int, int) - * - * Figure out the dimensions of this Spinner. The width comes from - * the widthMeasureSpec as Spinnners can't have their width set to - * UNSPECIFIED. The height is based on the height of the selected item - * plus padding. - */ - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int widthSize; - int heightSize; - - final int mPaddingLeft = getPaddingLeft(); - final int mPaddingTop = getPaddingTop(); - final int mPaddingRight = getPaddingRight(); - final int mPaddingBottom = getPaddingBottom(); - - mSpinnerPadding.left = mPaddingLeft > mSelectionLeftPadding ? mPaddingLeft - : mSelectionLeftPadding; - mSpinnerPadding.top = mPaddingTop > mSelectionTopPadding ? mPaddingTop - : mSelectionTopPadding; - mSpinnerPadding.right = mPaddingRight > mSelectionRightPadding ? mPaddingRight - : mSelectionRightPadding; - mSpinnerPadding.bottom = mPaddingBottom > mSelectionBottomPadding ? mPaddingBottom - : mSelectionBottomPadding; - - if (mDataChanged) { - handleDataChanged(); - } - - int preferredHeight = 0; - int preferredWidth = 0; - boolean needsMeasuring = true; - - int selectedPosition = getSelectedItemPosition(); - if (selectedPosition >= 0 && mAdapter != null && selectedPosition < mAdapter.getCount()) { - // Try looking in the recycler. (Maybe we were measured once already) - View view = mRecycler.get(selectedPosition); - if (view == null) { - // Make a new one - view = mAdapter.getView(selectedPosition, null, this); - } - - if (view != null) { - // Put in recycler for re-measuring and/or layout - mRecycler.put(selectedPosition, view); - } - - if (view != null) { - if (view.getLayoutParams() == null) { - mBlockLayoutRequests = true; - view.setLayoutParams(generateDefaultLayoutParams()); - mBlockLayoutRequests = false; - } - measureChild(view, widthMeasureSpec, heightMeasureSpec); - - preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom; - preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right; - - needsMeasuring = false; - } - } - - if (needsMeasuring) { - // No views -- just use padding - preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom; - if (widthMode == MeasureSpec.UNSPECIFIED) { - preferredWidth = mSpinnerPadding.left + mSpinnerPadding.right; - } - } - - preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight()); - preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth()); - - if (IS_HONEYCOMB) { - heightSize = resolveSizeAndState(preferredHeight, heightMeasureSpec, 0); - widthSize = resolveSizeAndState(preferredWidth, widthMeasureSpec, 0); - } else { - heightSize = resolveSize(preferredHeight, heightMeasureSpec); - widthSize = resolveSize(preferredWidth, widthMeasureSpec); - } - - setMeasuredDimension(widthSize, heightSize); - mHeightMeasureSpec = heightMeasureSpec; - mWidthMeasureSpec = widthMeasureSpec; - } - - int getChildHeight(View child) { - return child.getMeasuredHeight(); - } - - int getChildWidth(View child) { - return child.getMeasuredWidth(); - } - - @Override - protected ViewGroup.LayoutParams generateDefaultLayoutParams() { - return new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT); - } - - void recycleAllViews() { - final int childCount = getChildCount(); - final IcsAbsSpinner.RecycleBin recycleBin = mRecycler; - final int position = mFirstPosition; - - // All views go in recycler - for (int i = 0; i < childCount; i++) { - View v = getChildAt(i); - int index = position + i; - recycleBin.put(index, v); - } - } - - /** - * Jump directly to a specific item in the adapter data. - */ - public void setSelection(int position, boolean animate) { - // Animate only if requested position is already on screen somewhere - boolean shouldAnimate = animate && mFirstPosition <= position && - position <= mFirstPosition + getChildCount() - 1; - setSelectionInt(position, shouldAnimate); - } - - @Override - public void setSelection(int position) { - setNextSelectedPositionInt(position); - requestLayout(); - invalidate(); - } - - - /** - * Makes the item at the supplied position selected. - * - * @param position Position to select - * @param animate Should the transition be animated - * - */ - void setSelectionInt(int position, boolean animate) { - if (position != mOldSelectedPosition) { - mBlockLayoutRequests = true; - int delta = position - mSelectedPosition; - setNextSelectedPositionInt(position); - layout(delta, animate); - mBlockLayoutRequests = false; - } - } - - abstract void layout(int delta, boolean animate); - - @Override - public View getSelectedView() { - if (mItemCount > 0 && mSelectedPosition >= 0) { - return getChildAt(mSelectedPosition - mFirstPosition); - } else { - return null; - } - } - - /** - * Override to prevent spamming ourselves with layout requests - * as we place views - * - * @see android.view.View#requestLayout() - */ - @Override - public void requestLayout() { - if (!mBlockLayoutRequests) { - super.requestLayout(); - } - } - - @Override - public SpinnerAdapter getAdapter() { - return mAdapter; - } - - @Override - public int getCount() { - return mItemCount; - } - - /** - * Maps a point to a position in the list. - * - * @param x X in local coordinate - * @param y Y in local coordinate - * @return The position of the item which contains the specified point, or - * {@link #INVALID_POSITION} if the point does not intersect an item. - */ - public int pointToPosition(int x, int y) { - Rect frame = mTouchFrame; - if (frame == null) { - mTouchFrame = new Rect(); - frame = mTouchFrame; - } - - final int count = getChildCount(); - for (int i = count - 1; i >= 0; i--) { - View child = getChildAt(i); - if (child.getVisibility() == View.VISIBLE) { - child.getHitRect(frame); - if (frame.contains(x, y)) { - return mFirstPosition + i; - } - } - } - return INVALID_POSITION; - } - - static class SavedState extends BaseSavedState { - long selectedId; - int position; - - /** - * Constructor called from {@link AbsSpinner#onSaveInstanceState()} - */ - SavedState(Parcelable superState) { - super(superState); - } - - /** - * Constructor called from {@link #CREATOR} - */ - private SavedState(Parcel in) { - super(in); - selectedId = in.readLong(); - position = in.readInt(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeLong(selectedId); - out.writeInt(position); - } - - @Override - public String toString() { - return "AbsSpinner.SavedState{" - + Integer.toHexString(System.identityHashCode(this)) - + " selectedId=" + selectedId - + " position=" + position + "}"; - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - @Override - public Parcelable onSaveInstanceState() { - Parcelable superState = super.onSaveInstanceState(); - SavedState ss = new SavedState(superState); - ss.selectedId = getSelectedItemId(); - if (ss.selectedId >= 0) { - ss.position = getSelectedItemPosition(); - } else { - ss.position = INVALID_POSITION; - } - return ss; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState ss = (SavedState) state; - - super.onRestoreInstanceState(ss.getSuperState()); - - if (ss.selectedId >= 0) { - mDataChanged = true; - mNeedSync = true; - mSyncRowId = ss.selectedId; - mSyncPosition = ss.position; - mSyncMode = SYNC_SELECTED_POSITION; - requestLayout(); - } - } - - class RecycleBin { - private final SparseArray mScrapHeap = new SparseArray(); - - public void put(int position, View v) { - mScrapHeap.put(position, v); - } - - View get(int position) { - // System.out.print("Looking for " + position); - View result = mScrapHeap.get(position); - if (result != null) { - // System.out.println(" HIT"); - mScrapHeap.delete(position); - } else { - // System.out.println(" MISS"); - } - return result; - } - - void clear() { - final SparseArray scrapHeap = mScrapHeap; - final int count = scrapHeap.size(); - for (int i = 0; i < count; i++) { - final View view = scrapHeap.valueAt(i); - if (view != null) { - removeDetachedView(view, true); - } - } - scrapHeap.clear(); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java deleted file mode 100644 index c786dc5c1..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.database.DataSetObserver; -import android.os.Parcelable; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.util.SparseArray; -import android.view.ContextMenu; -import android.view.SoundEffectConstants; -import android.view.View; -import android.view.ViewDebug; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityNodeInfo; -import android.widget.Adapter; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; - - -/** - * An AdapterView is a view whose children are determined by an {@link Adapter}. - * - *

- * See {@link ListView}, {@link GridView}, {@link Spinner} and - * {@link Gallery} for commonly used subclasses of AdapterView. - * - *

- *

Developer Guides

- *

For more information about using AdapterView, read the - * Binding to Data with AdapterView - * developer guide.

- */ -public abstract class IcsAdapterView extends ViewGroup { - - /** - * The item view type returned by {@link Adapter#getItemViewType(int)} when - * the adapter does not want the item's view recycled. - */ - public static final int ITEM_VIEW_TYPE_IGNORE = -1; - - /** - * The item view type returned by {@link Adapter#getItemViewType(int)} when - * the item is a header or footer. - */ - public static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2; - - /** - * The position of the first child displayed - */ - @ViewDebug.ExportedProperty(category = "scrolling") - int mFirstPosition = 0; - - /** - * The offset in pixels from the top of the AdapterView to the top - * of the view to select during the next layout. - */ - int mSpecificTop; - - /** - * Position from which to start looking for mSyncRowId - */ - int mSyncPosition; - - /** - * Row id to look for when data has changed - */ - long mSyncRowId = INVALID_ROW_ID; - - /** - * Height of the view when mSyncPosition and mSyncRowId where set - */ - long mSyncHeight; - - /** - * True if we need to sync to mSyncRowId - */ - boolean mNeedSync = false; - - /** - * Indicates whether to sync based on the selection or position. Possible - * values are {@link #SYNC_SELECTED_POSITION} or - * {@link #SYNC_FIRST_POSITION}. - */ - int mSyncMode; - - /** - * Our height after the last layout - */ - private int mLayoutHeight; - - /** - * Sync based on the selected child - */ - static final int SYNC_SELECTED_POSITION = 0; - - /** - * Sync based on the first child displayed - */ - static final int SYNC_FIRST_POSITION = 1; - - /** - * Maximum amount of time to spend in {@link #findSyncPosition()} - */ - static final int SYNC_MAX_DURATION_MILLIS = 100; - - /** - * Indicates that this view is currently being laid out. - */ - boolean mInLayout = false; - - /** - * The listener that receives notifications when an item is selected. - */ - OnItemSelectedListener mOnItemSelectedListener; - - /** - * The listener that receives notifications when an item is clicked. - */ - OnItemClickListener mOnItemClickListener; - - /** - * The listener that receives notifications when an item is long clicked. - */ - OnItemLongClickListener mOnItemLongClickListener; - - /** - * True if the data has changed since the last layout - */ - boolean mDataChanged; - - /** - * The position within the adapter's data set of the item to select - * during the next layout. - */ - @ViewDebug.ExportedProperty(category = "list") - int mNextSelectedPosition = INVALID_POSITION; - - /** - * The item id of the item to select during the next layout. - */ - long mNextSelectedRowId = INVALID_ROW_ID; - - /** - * The position within the adapter's data set of the currently selected item. - */ - @ViewDebug.ExportedProperty(category = "list") - int mSelectedPosition = INVALID_POSITION; - - /** - * The item id of the currently selected item. - */ - long mSelectedRowId = INVALID_ROW_ID; - - /** - * View to show if there are no items to show. - */ - private View mEmptyView; - - /** - * The number of items in the current adapter. - */ - @ViewDebug.ExportedProperty(category = "list") - int mItemCount; - - /** - * The number of items in the adapter before a data changed event occurred. - */ - int mOldItemCount; - - /** - * Represents an invalid position. All valid positions are in the range 0 to 1 less than the - * number of items in the current adapter. - */ - public static final int INVALID_POSITION = -1; - - /** - * Represents an empty or invalid row id - */ - public static final long INVALID_ROW_ID = Long.MIN_VALUE; - - /** - * The last selected position we used when notifying - */ - int mOldSelectedPosition = INVALID_POSITION; - - /** - * The id of the last selected position we used when notifying - */ - long mOldSelectedRowId = INVALID_ROW_ID; - - /** - * Indicates what focusable state is requested when calling setFocusable(). - * In addition to this, this view has other criteria for actually - * determining the focusable state (such as whether its empty or the text - * filter is shown). - * - * @see #setFocusable(boolean) - * @see #checkFocus() - */ - private boolean mDesiredFocusableState; - private boolean mDesiredFocusableInTouchModeState; - - private SelectionNotifier mSelectionNotifier; - /** - * When set to true, calls to requestLayout() will not propagate up the parent hierarchy. - * This is used to layout the children during a layout pass. - */ - boolean mBlockLayoutRequests = false; - - public IcsAdapterView(Context context) { - super(context); - } - - public IcsAdapterView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public IcsAdapterView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - /** - * Register a callback to be invoked when an item in this AdapterView has - * been clicked. - * - * @param listener The callback that will be invoked. - */ - public void setOnItemClickListener(OnItemClickListener listener) { - mOnItemClickListener = listener; - } - - /** - * @return The callback to be invoked with an item in this AdapterView has - * been clicked, or null id no callback has been set. - */ - public final OnItemClickListener getOnItemClickListener() { - return mOnItemClickListener; - } - - /** - * Call the OnItemClickListener, if it is defined. - * - * @param view The view within the AdapterView that was clicked. - * @param position The position of the view in the adapter. - * @param id The row id of the item that was clicked. - * @return True if there was an assigned OnItemClickListener that was - * called, false otherwise is returned. - */ - public boolean performItemClick(View view, int position, long id) { - if (mOnItemClickListener != null) { - playSoundEffect(SoundEffectConstants.CLICK); - if (view != null) { - view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); - } - mOnItemClickListener.onItemClick(/*this*/null, view, position, id); - return true; - } - - return false; - } - - /** - * Interface definition for a callback to be invoked when an item in this - * view has been clicked and held. - */ - public interface OnItemLongClickListener { - /** - * Callback method to be invoked when an item in this view has been - * clicked and held. - * - * Implementers can call getItemAtPosition(position) if they need to access - * the data associated with the selected item. - * - * @param parent The AbsListView where the click happened - * @param view The view within the AbsListView that was clicked - * @param position The position of the view in the list - * @param id The row id of the item that was clicked - * - * @return true if the callback consumed the long click, false otherwise - */ - boolean onItemLongClick(IcsAdapterView parent, View view, int position, long id); - } - - - /** - * Register a callback to be invoked when an item in this AdapterView has - * been clicked and held - * - * @param listener The callback that will run - */ - public void setOnItemLongClickListener(OnItemLongClickListener listener) { - if (!isLongClickable()) { - setLongClickable(true); - } - mOnItemLongClickListener = listener; - } - - /** - * @return The callback to be invoked with an item in this AdapterView has - * been clicked and held, or null id no callback as been set. - */ - public final OnItemLongClickListener getOnItemLongClickListener() { - return mOnItemLongClickListener; - } - - /** - * Interface definition for a callback to be invoked when - * an item in this view has been selected. - */ - public interface OnItemSelectedListener { - /** - *

Callback method to be invoked when an item in this view has been - * selected. This callback is invoked only when the newly selected - * position is different from the previously selected position or if - * there was no selected item.

- * - * Impelmenters can call getItemAtPosition(position) if they need to access the - * data associated with the selected item. - * - * @param parent The AdapterView where the selection happened - * @param view The view within the AdapterView that was clicked - * @param position The position of the view in the adapter - * @param id The row id of the item that is selected - */ - void onItemSelected(IcsAdapterView parent, View view, int position, long id); - - /** - * Callback method to be invoked when the selection disappears from this - * view. The selection can disappear for instance when touch is activated - * or when the adapter becomes empty. - * - * @param parent The AdapterView that now contains no selected item. - */ - void onNothingSelected(IcsAdapterView parent); - } - - - /** - * Register a callback to be invoked when an item in this AdapterView has - * been selected. - * - * @param listener The callback that will run - */ - public void setOnItemSelectedListener(OnItemSelectedListener listener) { - mOnItemSelectedListener = listener; - } - - public final OnItemSelectedListener getOnItemSelectedListener() { - return mOnItemSelectedListener; - } - - /** - * Extra menu information provided to the - * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) } - * callback when a context menu is brought up for this AdapterView. - * - */ - public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo { - - public AdapterContextMenuInfo(View targetView, int position, long id) { - this.targetView = targetView; - this.position = position; - this.id = id; - } - - /** - * The child view for which the context menu is being displayed. This - * will be one of the children of this AdapterView. - */ - public View targetView; - - /** - * The position in the adapter for which the context menu is being - * displayed. - */ - public int position; - - /** - * The row id of the item for which the context menu is being displayed. - */ - public long id; - } - - /** - * Returns the adapter currently associated with this widget. - * - * @return The adapter used to provide this view's content. - */ - public abstract T getAdapter(); - - /** - * Sets the adapter that provides the data and the views to represent the data - * in this widget. - * - * @param adapter The adapter to use to create this view's content. - */ - public abstract void setAdapter(T adapter); - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @param child Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void addView(View child) { - throw new UnsupportedOperationException("addView(View) is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @param child Ignored. - * @param index Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void addView(View child, int index) { - throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @param child Ignored. - * @param params Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void addView(View child, LayoutParams params) { - throw new UnsupportedOperationException("addView(View, LayoutParams) " - + "is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @param child Ignored. - * @param index Ignored. - * @param params Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void addView(View child, int index, LayoutParams params) { - throw new UnsupportedOperationException("addView(View, int, LayoutParams) " - + "is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @param child Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void removeView(View child) { - throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @param index Ignored. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void removeViewAt(int index) { - throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView"); - } - - /** - * This method is not supported and throws an UnsupportedOperationException when called. - * - * @throws UnsupportedOperationException Every time this method is invoked. - */ - @Override - public void removeAllViews() { - throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView"); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mLayoutHeight = getHeight(); - } - - /** - * Return the position of the currently selected item within the adapter's data set - * - * @return int Position (starting at 0), or {@link #INVALID_POSITION} if there is nothing selected. - */ - @ViewDebug.CapturedViewProperty - public int getSelectedItemPosition() { - return mNextSelectedPosition; - } - - /** - * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID} - * if nothing is selected. - */ - @ViewDebug.CapturedViewProperty - public long getSelectedItemId() { - return mNextSelectedRowId; - } - - /** - * @return The view corresponding to the currently selected item, or null - * if nothing is selected - */ - public abstract View getSelectedView(); - - /** - * @return The data corresponding to the currently selected item, or - * null if there is nothing selected. - */ - public Object getSelectedItem() { - T adapter = getAdapter(); - int selection = getSelectedItemPosition(); - if (adapter != null && adapter.getCount() > 0 && selection >= 0) { - return adapter.getItem(selection); - } else { - return null; - } - } - - /** - * @return The number of items owned by the Adapter associated with this - * AdapterView. (This is the number of data items, which may be - * larger than the number of visible views.) - */ - @ViewDebug.CapturedViewProperty - public int getCount() { - return mItemCount; - } - - /** - * Get the position within the adapter's data set for the view, where view is a an adapter item - * or a descendant of an adapter item. - * - * @param view an adapter item, or a descendant of an adapter item. This must be visible in this - * AdapterView at the time of the call. - * @return the position within the adapter's data set of the view, or {@link #INVALID_POSITION} - * if the view does not correspond to a list item (or it is not currently visible). - */ - public int getPositionForView(View view) { - View listItem = view; - try { - View v; - while (!(v = (View) listItem.getParent()).equals(this)) { - listItem = v; - } - } catch (ClassCastException e) { - // We made it up to the window without find this list view - return INVALID_POSITION; - } - - // Search the children for the list item - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - if (getChildAt(i).equals(listItem)) { - return mFirstPosition + i; - } - } - - // Child not found! - return INVALID_POSITION; - } - - /** - * Returns the position within the adapter's data set for the first item - * displayed on screen. - * - * @return The position within the adapter's data set - */ - public int getFirstVisiblePosition() { - return mFirstPosition; - } - - /** - * Returns the position within the adapter's data set for the last item - * displayed on screen. - * - * @return The position within the adapter's data set - */ - public int getLastVisiblePosition() { - return mFirstPosition + getChildCount() - 1; - } - - /** - * Sets the currently selected item. To support accessibility subclasses that - * override this method must invoke the overriden super method first. - * - * @param position Index (starting at 0) of the data item to be selected. - */ - public abstract void setSelection(int position); - - /** - * Sets the view to show if the adapter is empty - */ - public void setEmptyView(View emptyView) { - mEmptyView = emptyView; - - final T adapter = getAdapter(); - final boolean empty = ((adapter == null) || adapter.isEmpty()); - updateEmptyStatus(empty); - } - - /** - * When the current adapter is empty, the AdapterView can display a special view - * call the empty view. The empty view is used to provide feedback to the user - * that no data is available in this AdapterView. - * - * @return The view to show if the adapter is empty. - */ - public View getEmptyView() { - return mEmptyView; - } - - /** - * Indicates whether this view is in filter mode. Filter mode can for instance - * be enabled by a user when typing on the keyboard. - * - * @return True if the view is in filter mode, false otherwise. - */ - boolean isInFilterMode() { - return false; - } - - @Override - public void setFocusable(boolean focusable) { - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.getCount() == 0; - - mDesiredFocusableState = focusable; - if (!focusable) { - mDesiredFocusableInTouchModeState = false; - } - - super.setFocusable(focusable && (!empty || isInFilterMode())); - } - - @Override - public void setFocusableInTouchMode(boolean focusable) { - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.getCount() == 0; - - mDesiredFocusableInTouchModeState = focusable; - if (focusable) { - mDesiredFocusableState = true; - } - - super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode())); - } - - void checkFocus() { - final T adapter = getAdapter(); - final boolean empty = adapter == null || adapter.getCount() == 0; - final boolean focusable = !empty || isInFilterMode(); - // The order in which we set focusable in touch mode/focusable may matter - // for the client, see View.setFocusableInTouchMode() comments for more - // details - super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState); - super.setFocusable(focusable && mDesiredFocusableState); - if (mEmptyView != null) { - updateEmptyStatus((adapter == null) || adapter.isEmpty()); - } - } - - /** - * Update the status of the list based on the empty parameter. If empty is true and - * we have an empty view, display it. In all the other cases, make sure that the listview - * is VISIBLE and that the empty view is GONE (if it's not null). - */ - private void updateEmptyStatus(boolean empty) { - if (isInFilterMode()) { - empty = false; - } - - if (empty) { - if (mEmptyView != null) { - mEmptyView.setVisibility(View.VISIBLE); - setVisibility(View.GONE); - } else { - // If the caller just removed our empty view, make sure the list view is visible - setVisibility(View.VISIBLE); - } - - // We are now GONE, so pending layouts will not be dispatched. - // Force one here to make sure that the state of the list matches - // the state of the adapter. - if (mDataChanged) { - this.onLayout(false, getLeft(), getTop(), getRight(), getBottom()); - } - } else { - if (mEmptyView != null) mEmptyView.setVisibility(View.GONE); - setVisibility(View.VISIBLE); - } - } - - /** - * Gets the data associated with the specified position in the list. - * - * @param position Which data to get - * @return The data associated with the specified position in the list - */ - public Object getItemAtPosition(int position) { - T adapter = getAdapter(); - return (adapter == null || position < 0) ? null : adapter.getItem(position); - } - - public long getItemIdAtPosition(int position) { - T adapter = getAdapter(); - return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position); - } - - @Override - public void setOnClickListener(OnClickListener l) { - throw new RuntimeException("Don't call setOnClickListener for an AdapterView. " - + "You probably want setOnItemClickListener instead"); - } - - /** - * Override to prevent freezing of any views created by the adapter. - */ - @Override - protected void dispatchSaveInstanceState(SparseArray container) { - dispatchFreezeSelfOnly(container); - } - - /** - * Override to prevent thawing of any views created by the adapter. - */ - @Override - protected void dispatchRestoreInstanceState(SparseArray container) { - dispatchThawSelfOnly(container); - } - - class AdapterDataSetObserver extends DataSetObserver { - - private Parcelable mInstanceState = null; - - @Override - public void onChanged() { - mDataChanged = true; - mOldItemCount = mItemCount; - mItemCount = getAdapter().getCount(); - - // Detect the case where a cursor that was previously invalidated has - // been repopulated with new data. - if (IcsAdapterView.this.getAdapter().hasStableIds() && mInstanceState != null - && mOldItemCount == 0 && mItemCount > 0) { - IcsAdapterView.this.onRestoreInstanceState(mInstanceState); - mInstanceState = null; - } else { - rememberSyncState(); - } - checkFocus(); - requestLayout(); - } - - @Override - public void onInvalidated() { - mDataChanged = true; - - if (IcsAdapterView.this.getAdapter().hasStableIds()) { - // Remember the current state for the case where our hosting activity is being - // stopped and later restarted - mInstanceState = IcsAdapterView.this.onSaveInstanceState(); - } - - // Data is invalid so we should reset our state - mOldItemCount = mItemCount; - mItemCount = 0; - mSelectedPosition = INVALID_POSITION; - mSelectedRowId = INVALID_ROW_ID; - mNextSelectedPosition = INVALID_POSITION; - mNextSelectedRowId = INVALID_ROW_ID; - mNeedSync = false; - - checkFocus(); - requestLayout(); - } - - public void clearSavedState() { - mInstanceState = null; - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - removeCallbacks(mSelectionNotifier); - } - - private class SelectionNotifier implements Runnable { - public void run() { - if (mDataChanged) { - // Data has changed between when this SelectionNotifier - // was posted and now. We need to wait until the AdapterView - // has been synched to the new data. - if (getAdapter() != null) { - post(this); - } - } else { - fireOnSelected(); - } - } - } - - void selectionChanged() { - if (mOnItemSelectedListener != null) { - if (mInLayout || mBlockLayoutRequests) { - // If we are in a layout traversal, defer notification - // by posting. This ensures that the view tree is - // in a consistent state and is able to accomodate - // new layout or invalidate requests. - if (mSelectionNotifier == null) { - mSelectionNotifier = new SelectionNotifier(); - } - post(mSelectionNotifier); - } else { - fireOnSelected(); - } - } - - // we fire selection events here not in View - if (mSelectedPosition != ListView.INVALID_POSITION && isShown() && !isInTouchMode()) { - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - } - } - - private void fireOnSelected() { - if (mOnItemSelectedListener == null) - return; - - int selection = this.getSelectedItemPosition(); - if (selection >= 0) { - View v = getSelectedView(); - mOnItemSelectedListener.onItemSelected(this, v, selection, - getAdapter().getItemId(selection)); - } else { - mOnItemSelectedListener.onNothingSelected(this); - } - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - View selectedView = getSelectedView(); - if (selectedView != null && selectedView.getVisibility() == VISIBLE - && selectedView.dispatchPopulateAccessibilityEvent(event)) { - return true; - } - return false; - } - - @Override - public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { - if (super.onRequestSendAccessibilityEvent(child, event)) { - // Add a record for ourselves as well. - AccessibilityEvent record = AccessibilityEvent.obtain(); - onInitializeAccessibilityEvent(record); - // Populate with the text of the requesting child. - child.dispatchPopulateAccessibilityEvent(record); - event.appendRecord(record); - return true; - } - return false; - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setScrollable(isScrollableForAccessibility()); - View selectedView = getSelectedView(); - if (selectedView != null) { - info.setEnabled(selectedView.isEnabled()); - } - } - - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setScrollable(isScrollableForAccessibility()); - View selectedView = getSelectedView(); - if (selectedView != null) { - event.setEnabled(selectedView.isEnabled()); - } - event.setCurrentItemIndex(getSelectedItemPosition()); - event.setFromIndex(getFirstVisiblePosition()); - event.setToIndex(getLastVisiblePosition()); - event.setItemCount(getCount()); - } - - private boolean isScrollableForAccessibility() { - T adapter = getAdapter(); - if (adapter != null) { - final int itemCount = adapter.getCount(); - return itemCount > 0 - && (getFirstVisiblePosition() > 0 || getLastVisiblePosition() < itemCount - 1); - } - return false; - } - - @Override - protected boolean canAnimate() { - return super.canAnimate() && mItemCount > 0; - } - - void handleDataChanged() { - final int count = mItemCount; - boolean found = false; - - if (count > 0) { - - int newPos; - - // Find the row we are supposed to sync to - if (mNeedSync) { - // Update this first, since setNextSelectedPositionInt inspects - // it - mNeedSync = false; - - // See if we can find a position in the new data with the same - // id as the old selection - newPos = findSyncPosition(); - if (newPos >= 0) { - // Verify that new selection is selectable - int selectablePos = lookForSelectablePosition(newPos, true); - if (selectablePos == newPos) { - // Same row id is selected - setNextSelectedPositionInt(newPos); - found = true; - } - } - } - if (!found) { - // Try to use the same position if we can't find matching data - newPos = getSelectedItemPosition(); - - // Pin position to the available range - if (newPos >= count) { - newPos = count - 1; - } - if (newPos < 0) { - newPos = 0; - } - - // Make sure we select something selectable -- first look down - int selectablePos = lookForSelectablePosition(newPos, true); - if (selectablePos < 0) { - // Looking down didn't work -- try looking up - selectablePos = lookForSelectablePosition(newPos, false); - } - if (selectablePos >= 0) { - setNextSelectedPositionInt(selectablePos); - checkSelectionChanged(); - found = true; - } - } - } - if (!found) { - // Nothing is selected - mSelectedPosition = INVALID_POSITION; - mSelectedRowId = INVALID_ROW_ID; - mNextSelectedPosition = INVALID_POSITION; - mNextSelectedRowId = INVALID_ROW_ID; - mNeedSync = false; - checkSelectionChanged(); - } - } - - void checkSelectionChanged() { - if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) { - selectionChanged(); - mOldSelectedPosition = mSelectedPosition; - mOldSelectedRowId = mSelectedRowId; - } - } - - /** - * Searches the adapter for a position matching mSyncRowId. The search starts at mSyncPosition - * and then alternates between moving up and moving down until 1) we find the right position, or - * 2) we run out of time, or 3) we have looked at every position - * - * @return Position of the row that matches mSyncRowId, or {@link #INVALID_POSITION} if it can't - * be found - */ - int findSyncPosition() { - int count = mItemCount; - - if (count == 0) { - return INVALID_POSITION; - } - - long idToMatch = mSyncRowId; - int seed = mSyncPosition; - - // If there isn't a selection don't hunt for it - if (idToMatch == INVALID_ROW_ID) { - return INVALID_POSITION; - } - - // Pin seed to reasonable values - seed = Math.max(0, seed); - seed = Math.min(count - 1, seed); - - long endTime = SystemClock.uptimeMillis() + SYNC_MAX_DURATION_MILLIS; - - long rowId; - - // first position scanned so far - int first = seed; - - // last position scanned so far - int last = seed; - - // True if we should move down on the next iteration - boolean next = false; - - // True when we have looked at the first item in the data - boolean hitFirst; - - // True when we have looked at the last item in the data - boolean hitLast; - - // Get the item ID locally (instead of getItemIdAtPosition), so - // we need the adapter - T adapter = getAdapter(); - if (adapter == null) { - return INVALID_POSITION; - } - - while (SystemClock.uptimeMillis() <= endTime) { - rowId = adapter.getItemId(seed); - if (rowId == idToMatch) { - // Found it! - return seed; - } - - hitLast = last == count - 1; - hitFirst = first == 0; - - if (hitLast && hitFirst) { - // Looked at everything - break; - } - - if (hitFirst || (next && !hitLast)) { - // Either we hit the top, or we are trying to move down - last++; - seed = last; - // Try going up next time - next = false; - } else if (hitLast || (!next && !hitFirst)) { - // Either we hit the bottom, or we are trying to move up - first--; - seed = first; - // Try going down next time - next = true; - } - - } - - return INVALID_POSITION; - } - - /** - * Find a position that can be selected (i.e., is not a separator). - * - * @param position The starting position to look at. - * @param lookDown Whether to look down for other positions. - * @return The next selectable position starting at position and then searching either up or - * down. Returns {@link #INVALID_POSITION} if nothing can be found. - */ - int lookForSelectablePosition(int position, boolean lookDown) { - return position; - } - - /** - * Utility to keep mSelectedPosition and mSelectedRowId in sync - * @param position Our current position - */ - void setSelectedPositionInt(int position) { - mSelectedPosition = position; - mSelectedRowId = getItemIdAtPosition(position); - } - - /** - * Utility to keep mNextSelectedPosition and mNextSelectedRowId in sync - * @param position Intended value for mSelectedPosition the next time we go - * through layout - */ - void setNextSelectedPositionInt(int position) { - mNextSelectedPosition = position; - mNextSelectedRowId = getItemIdAtPosition(position); - // If we are trying to sync to the selection, update that too - if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) { - mSyncPosition = position; - mSyncRowId = mNextSelectedRowId; - } - } - - /** - * Remember enough information to restore the screen state when the data has - * changed. - * - */ - void rememberSyncState() { - if (getChildCount() > 0) { - mNeedSync = true; - mSyncHeight = mLayoutHeight; - if (mSelectedPosition >= 0) { - // Sync the selection state - View v = getChildAt(mSelectedPosition - mFirstPosition); - mSyncRowId = mNextSelectedRowId; - mSyncPosition = mNextSelectedPosition; - if (v != null) { - mSpecificTop = v.getTop(); - } - mSyncMode = SYNC_SELECTED_POSITION; - } else { - // Sync the based on the offset of the first view - View v = getChildAt(0); - T adapter = getAdapter(); - if (mFirstPosition >= 0 && mFirstPosition < adapter.getCount()) { - mSyncRowId = adapter.getItemId(mFirstPosition); - } else { - mSyncRowId = NO_ID; - } - mSyncPosition = mFirstPosition; - if (v != null) { - mSpecificTop = v.getTop(); - } - mSyncMode = SYNC_FIRST_POSITION; - } - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java deleted file mode 100644 index a78b3f71b..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.drawable.Drawable; - -/** - * A version of {@link android.graphics.drawable.ColorDrawable} that respects bounds. - */ -public class IcsColorDrawable extends Drawable { - private int color; - private final Paint paint = new Paint(); - - public IcsColorDrawable(int color) { - this.color = color; - } - - @Override public void draw(Canvas canvas) { - if ((color >>> 24) != 0) { - paint.setColor(color); - canvas.drawRect(getBounds(), paint); - } - } - - @Override - public void setAlpha(int alpha) { - if (alpha != (color >>> 24)) { - color = (color & 0x00FFFFFF) & (alpha << 24); - invalidateSelf(); - } - } - - @Override public void setColorFilter(ColorFilter colorFilter) { - //Ignored - } - - @Override public int getOpacity() { - return color >>> 24; - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java deleted file mode 100644 index 4947c41df..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java +++ /dev/null @@ -1,410 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.View; -import android.widget.LinearLayout; - -import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout; - -/** - * A simple extension of a regular linear layout that supports the divider API - * of Android 4.0+. The dividers are added adjacent to the children by changing - * their layout params. If you need to rely on the margins which fall in the - * same orientation as the layout you should wrap the child in a simple - * {@link android.widget.FrameLayout} so it can receive the margin. - */ -public class IcsLinearLayout extends NineLinearLayout { - private static final int[] R_styleable_LinearLayout = new int[] { - /* 0 */ android.R.attr.divider, - /* 1 */ android.R.attr.measureWithLargestChild, - /* 2 */ android.R.attr.showDividers, - /* 3 */ android.R.attr.dividerPadding, - }; - private static final int LinearLayout_divider = 0; - private static final int LinearLayout_measureWithLargestChild = 1; - private static final int LinearLayout_showDividers = 2; - private static final int LinearLayout_dividerPadding = 3; - - /** - * Don't show any dividers. - */ - public static final int SHOW_DIVIDER_NONE = 0; - /** - * Show a divider at the beginning of the group. - */ - public static final int SHOW_DIVIDER_BEGINNING = 1; - /** - * Show dividers between each item in the group. - */ - public static final int SHOW_DIVIDER_MIDDLE = 2; - /** - * Show a divider at the end of the group. - */ - public static final int SHOW_DIVIDER_END = 4; - - - private Drawable mDivider; - private int mDividerWidth; - private int mDividerHeight; - private int mShowDividers; - private int mDividerPadding; - - private boolean mUseLargestChild; - - public IcsLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/R_styleable_LinearLayout); - - setDividerDrawable(a.getDrawable(/*com.android.internal.R.styleable.*/LinearLayout_divider)); - mShowDividers = a.getInt(/*com.android.internal.R.styleable.*/LinearLayout_showDividers, SHOW_DIVIDER_NONE); - mDividerPadding = a.getDimensionPixelSize(/*com.android.internal.R.styleable.*/LinearLayout_dividerPadding, 0); - mUseLargestChild = a.getBoolean(/*com.android.internal.R.styleable.*/LinearLayout_measureWithLargestChild, false); - - a.recycle(); - } - - /** - * Set how dividers should be shown between items in this layout - * - * @param showDividers One or more of {@link #SHOW_DIVIDER_BEGINNING}, - * {@link #SHOW_DIVIDER_MIDDLE}, or {@link #SHOW_DIVIDER_END}, - * or {@link #SHOW_DIVIDER_NONE} to show no dividers. - */ - public void setShowDividers(int showDividers) { - if (showDividers != mShowDividers) { - requestLayout(); - invalidate(); //XXX This is required if you are toggling a divider off - } - mShowDividers = showDividers; - } - - /** - * @return A flag set indicating how dividers should be shown around items. - * @see #setShowDividers(int) - */ - public int getShowDividers() { - return mShowDividers; - } - - /** - * Set a drawable to be used as a divider between items. - * @param divider Drawable that will divide each item. - * @see #setShowDividers(int) - */ - public void setDividerDrawable(Drawable divider) { - if (divider == mDivider) { - return; - } - mDivider = divider; - if (divider != null) { - mDividerWidth = divider.getIntrinsicWidth(); - mDividerHeight = divider.getIntrinsicHeight(); - } else { - mDividerWidth = 0; - mDividerHeight = 0; - } - setWillNotDraw(divider == null); - requestLayout(); - } - - /** - * Set padding displayed on both ends of dividers. - * - * @param padding Padding value in pixels that will be applied to each end - * - * @see #setShowDividers(int) - * @see #setDividerDrawable(Drawable) - * @see #getDividerPadding() - */ - public void setDividerPadding(int padding) { - mDividerPadding = padding; - } - - /** - * Get the padding size used to inset dividers in pixels - * - * @see #setShowDividers(int) - * @see #setDividerDrawable(Drawable) - * @see #setDividerPadding(int) - */ - public int getDividerPadding() { - return mDividerPadding; - } - - /** - * Get the width of the current divider drawable. - * - * @hide Used internally by framework. - */ - public int getDividerWidth() { - return mDividerWidth; - } - - @Override - protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { - final int index = indexOfChild(child); - final int orientation = getOrientation(); - final LayoutParams params = (LayoutParams) child.getLayoutParams(); - if (hasDividerBeforeChildAt(index)) { - if (orientation == VERTICAL) { - //Account for the divider by pushing everything up - params.topMargin = mDividerHeight; - } else { - //Account for the divider by pushing everything left - params.leftMargin = mDividerWidth; - } - } - - final int count = getChildCount(); - if (index == count - 1) { - if (hasDividerBeforeChildAt(count)) { - if (orientation == VERTICAL) { - params.bottomMargin = mDividerHeight; - } else { - params.rightMargin = mDividerWidth; - } - } - } - super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); - } - - @Override - protected void onDraw(Canvas canvas) { - if (mDivider != null) { - if (getOrientation() == VERTICAL) { - drawDividersVertical(canvas); - } else { - drawDividersHorizontal(canvas); - } - } - super.onDraw(canvas); - } - - void drawDividersVertical(Canvas canvas) { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - if (child != null && child.getVisibility() != GONE) { - if (hasDividerBeforeChildAt(i)) { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - final int top = child.getTop() - lp.topMargin/* - mDividerHeight*/; - drawHorizontalDivider(canvas, top); - } - } - } - - if (hasDividerBeforeChildAt(count)) { - final View child = getChildAt(count - 1); - int bottom = 0; - if (child == null) { - bottom = getHeight() - getPaddingBottom() - mDividerHeight; - } else { - //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - bottom = child.getBottom()/* + lp.bottomMargin*/; - } - drawHorizontalDivider(canvas, bottom); - } - } - - void drawDividersHorizontal(Canvas canvas) { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - final View child = getChildAt(i); - - if (child != null && child.getVisibility() != GONE) { - if (hasDividerBeforeChildAt(i)) { - final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - final int left = child.getLeft() - lp.leftMargin/* - mDividerWidth*/; - drawVerticalDivider(canvas, left); - } - } - } - - if (hasDividerBeforeChildAt(count)) { - final View child = getChildAt(count - 1); - int right = 0; - if (child == null) { - right = getWidth() - getPaddingRight() - mDividerWidth; - } else { - //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); - right = child.getRight()/* + lp.rightMargin*/; - } - drawVerticalDivider(canvas, right); - } - } - - void drawHorizontalDivider(Canvas canvas, int top) { - mDivider.setBounds(getPaddingLeft() + mDividerPadding, top, - getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight); - mDivider.draw(canvas); - } - - void drawVerticalDivider(Canvas canvas, int left) { - mDivider.setBounds(left, getPaddingTop() + mDividerPadding, - left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding); - mDivider.draw(canvas); - } - - /** - * Determines where to position dividers between children. - * - * @param childIndex Index of child to check for preceding divider - * @return true if there should be a divider before the child at childIndex - * @hide Pending API consideration. Currently only used internally by the system. - */ - protected boolean hasDividerBeforeChildAt(int childIndex) { - if (childIndex == 0) { - return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0; - } else if (childIndex == getChildCount()) { - return (mShowDividers & SHOW_DIVIDER_END) != 0; - } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) { - boolean hasVisibleViewBefore = false; - for (int i = childIndex - 1; i >= 0; i--) { - if (getChildAt(i).getVisibility() != GONE) { - hasVisibleViewBefore = true; - break; - } - } - return hasVisibleViewBefore; - } - return false; - } - - /** - * When true, all children with a weight will be considered having - * the minimum size of the largest child. If false, all children are - * measured normally. - * - * @return True to measure children with a weight using the minimum - * size of the largest child, false otherwise. - * - * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild - */ - public boolean isMeasureWithLargestChildEnabled() { - return mUseLargestChild; - } - - /** - * When set to true, all children with a weight will be considered having - * the minimum size of the largest child. If false, all children are - * measured normally. - * - * Disabled by default. - * - * @param enabled True to measure children with a weight using the - * minimum size of the largest child, false otherwise. - * - * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild - */ - public void setMeasureWithLargestChildEnabled(boolean enabled) { - mUseLargestChild = enabled; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - if (mUseLargestChild) { - final int orientation = getOrientation(); - switch (orientation) { - case HORIZONTAL: - useLargestChildHorizontal(); - break; - - case VERTICAL: - useLargestChildVertical(); - break; - } - } - } - - private void useLargestChildHorizontal() { - final int childCount = getChildCount(); - - // Find largest child width - int largestChildWidth = 0; - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - largestChildWidth = Math.max(child.getMeasuredWidth(), largestChildWidth); - } - - int totalWidth = 0; - // Re-measure childs - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - - if (child == null || child.getVisibility() == View.GONE) { - continue; - } - - final LinearLayout.LayoutParams lp = - (LinearLayout.LayoutParams) child.getLayoutParams(); - - float childExtra = lp.weight; - if (childExtra > 0) { - child.measure( - MeasureSpec.makeMeasureSpec(largestChildWidth, - MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), - MeasureSpec.EXACTLY)); - totalWidth += largestChildWidth; - - } else { - totalWidth += child.getMeasuredWidth(); - } - - totalWidth += lp.leftMargin + lp.rightMargin; - } - - totalWidth += getPaddingLeft() + getPaddingRight(); - setMeasuredDimension(totalWidth, getMeasuredHeight()); - } - - private void useLargestChildVertical() { - final int childCount = getChildCount(); - - // Find largest child width - int largestChildHeight = 0; - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - largestChildHeight = Math.max(child.getMeasuredHeight(), largestChildHeight); - } - - int totalHeight = 0; - // Re-measure childs - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - - if (child == null || child.getVisibility() == View.GONE) { - continue; - } - - final LinearLayout.LayoutParams lp = - (LinearLayout.LayoutParams) child.getLayoutParams(); - - float childExtra = lp.weight; - if (childExtra > 0) { - child.measure( - MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), - MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(largestChildHeight, - MeasureSpec.EXACTLY)); - totalHeight += largestChildHeight; - - } else { - totalHeight += child.getMeasuredHeight(); - } - - totalHeight += lp.leftMargin + lp.rightMargin; - } - - totalHeight += getPaddingLeft() + getPaddingRight(); - setMeasuredDimension(getMeasuredWidth(), totalHeight); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java deleted file mode 100644 index d13c6cea9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java +++ /dev/null @@ -1,644 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import com.actionbarsherlock.R; - -import android.content.Context; -import android.content.res.Resources; -import android.database.DataSetObserver; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.os.Handler; -import android.util.AttributeSet; -import android.view.ContextThemeWrapper; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.View.OnTouchListener; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.LinearLayout; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.PopupWindow; - -/** - * A proxy between pre- and post-Honeycomb implementations of this class. - */ -public class IcsListPopupWindow { - /** - * This value controls the length of time that the user - * must leave a pointer down without scrolling to expand - * the autocomplete dropdown list to cover the IME. - */ - private static final int EXPAND_LIST_TIMEOUT = 250; - - private Context mContext; - private PopupWindow mPopup; - private ListAdapter mAdapter; - private DropDownListView mDropDownList; - - private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT; - private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT; - private int mDropDownHorizontalOffset; - private int mDropDownVerticalOffset; - private boolean mDropDownVerticalOffsetSet; - - private int mListItemExpandMaximum = Integer.MAX_VALUE; - - private View mPromptView; - private int mPromptPosition = POSITION_PROMPT_ABOVE; - - private DataSetObserver mObserver; - - private View mDropDownAnchorView; - - private Drawable mDropDownListHighlight; - - private AdapterView.OnItemClickListener mItemClickListener; - private AdapterView.OnItemSelectedListener mItemSelectedListener; - - private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable(); - private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor(); - private final PopupScrollListener mScrollListener = new PopupScrollListener(); - private final ListSelectorHider mHideSelector = new ListSelectorHider(); - - private Handler mHandler = new Handler(); - - private Rect mTempRect = new Rect(); - - private boolean mModal; - - public static final int POSITION_PROMPT_ABOVE = 0; - public static final int POSITION_PROMPT_BELOW = 1; - - public IcsListPopupWindow(Context context) { - this(context, null, R.attr.listPopupWindowStyle); - } - - public IcsListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) { - mContext = context; - mPopup = new PopupWindow(context, attrs, defStyleAttr); - mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - } - - public IcsListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - mContext = context; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { - Context wrapped = new ContextThemeWrapper(context, defStyleRes); - mPopup = new PopupWindow(wrapped, attrs, defStyleAttr); - } else { - mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes); - } - mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - } - - public void setAdapter(ListAdapter adapter) { - if (mObserver == null) { - mObserver = new PopupDataSetObserver(); - } else if (mAdapter != null) { - mAdapter.unregisterDataSetObserver(mObserver); - } - mAdapter = adapter; - if (mAdapter != null) { - adapter.registerDataSetObserver(mObserver); - } - - if (mDropDownList != null) { - mDropDownList.setAdapter(mAdapter); - } - } - - public void setPromptPosition(int position) { - mPromptPosition = position; - } - - public void setModal(boolean modal) { - mModal = true; - mPopup.setFocusable(modal); - } - - public void setBackgroundDrawable(Drawable d) { - mPopup.setBackgroundDrawable(d); - } - - public void setAnchorView(View anchor) { - mDropDownAnchorView = anchor; - } - - public void setHorizontalOffset(int offset) { - mDropDownHorizontalOffset = offset; - } - - public void setVerticalOffset(int offset) { - mDropDownVerticalOffset = offset; - mDropDownVerticalOffsetSet = true; - } - - public void setContentWidth(int width) { - Drawable popupBackground = mPopup.getBackground(); - if (popupBackground != null) { - popupBackground.getPadding(mTempRect); - mDropDownWidth = mTempRect.left + mTempRect.right + width; - } else { - mDropDownWidth = width; - } - } - - public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) { - mItemClickListener = clickListener; - } - - public void show() { - int height = buildDropDown(); - - int widthSpec = 0; - int heightSpec = 0; - - boolean noInputMethod = isInputMethodNotNeeded(); - //XXX mPopup.setAllowScrollingAnchorParent(!noInputMethod); - - if (mPopup.isShowing()) { - if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { - // The call to PopupWindow's update method below can accept -1 for any - // value you do not want to update. - widthSpec = -1; - } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { - widthSpec = mDropDownAnchorView.getWidth(); - } else { - widthSpec = mDropDownWidth; - } - - if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { - // The call to PopupWindow's update method below can accept -1 for any - // value you do not want to update. - heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT; - if (noInputMethod) { - mPopup.setWindowLayoutMode( - mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? - ViewGroup.LayoutParams.MATCH_PARENT : 0, 0); - } else { - mPopup.setWindowLayoutMode( - mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? - ViewGroup.LayoutParams.MATCH_PARENT : 0, - ViewGroup.LayoutParams.MATCH_PARENT); - } - } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { - heightSpec = height; - } else { - heightSpec = mDropDownHeight; - } - - mPopup.setOutsideTouchable(true); - - mPopup.update(mDropDownAnchorView, mDropDownHorizontalOffset, - mDropDownVerticalOffset, widthSpec, heightSpec); - } else { - if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { - widthSpec = ViewGroup.LayoutParams.MATCH_PARENT; - } else { - if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { - mPopup.setWidth(mDropDownAnchorView.getWidth()); - } else { - mPopup.setWidth(mDropDownWidth); - } - } - - if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { - heightSpec = ViewGroup.LayoutParams.MATCH_PARENT; - } else { - if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { - mPopup.setHeight(height); - } else { - mPopup.setHeight(mDropDownHeight); - } - } - - mPopup.setWindowLayoutMode(widthSpec, heightSpec); - //XXX mPopup.setClipToScreenEnabled(true); - - // use outside touchable to dismiss drop down when touching outside of it, so - // only set this if the dropdown is not always visible - mPopup.setOutsideTouchable(true); - mPopup.setTouchInterceptor(mTouchInterceptor); - mPopup.showAsDropDown(mDropDownAnchorView, - mDropDownHorizontalOffset, mDropDownVerticalOffset); - mDropDownList.setSelection(ListView.INVALID_POSITION); - - if (!mModal || mDropDownList.isInTouchMode()) { - clearListSelection(); - } - if (!mModal) { - mHandler.post(mHideSelector); - } - } - } - - public void dismiss() { - mPopup.dismiss(); - if (mPromptView != null) { - final ViewParent parent = mPromptView.getParent(); - if (parent instanceof ViewGroup) { - final ViewGroup group = (ViewGroup) parent; - group.removeView(mPromptView); - } - } - mPopup.setContentView(null); - mDropDownList = null; - mHandler.removeCallbacks(mResizePopupRunnable); - } - - public void setOnDismissListener(PopupWindow.OnDismissListener listener) { - mPopup.setOnDismissListener(listener); - } - - public void setInputMethodMode(int mode) { - mPopup.setInputMethodMode(mode); - } - - public void clearListSelection() { - final DropDownListView list = mDropDownList; - if (list != null) { - // WARNING: Please read the comment where mListSelectionHidden is declared - list.mListSelectionHidden = true; - //XXX list.hideSelector(); - list.requestLayout(); - } - } - - public boolean isShowing() { - return mPopup.isShowing(); - } - - private boolean isInputMethodNotNeeded() { - return mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; - } - - public ListView getListView() { - return mDropDownList; - } - - private int buildDropDown() { - ViewGroup dropDownView; - int otherHeights = 0; - - if (mDropDownList == null) { - Context context = mContext; - - mDropDownList = new DropDownListView(context, !mModal); - if (mDropDownListHighlight != null) { - mDropDownList.setSelector(mDropDownListHighlight); - } - mDropDownList.setAdapter(mAdapter); - mDropDownList.setOnItemClickListener(mItemClickListener); - mDropDownList.setFocusable(true); - mDropDownList.setFocusableInTouchMode(true); - mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - public void onItemSelected(AdapterView parent, View view, - int position, long id) { - - if (position != -1) { - DropDownListView dropDownList = mDropDownList; - - if (dropDownList != null) { - dropDownList.mListSelectionHidden = false; - } - } - } - - public void onNothingSelected(AdapterView parent) { - } - }); - mDropDownList.setOnScrollListener(mScrollListener); - - if (mItemSelectedListener != null) { - mDropDownList.setOnItemSelectedListener(mItemSelectedListener); - } - - dropDownView = mDropDownList; - - View hintView = mPromptView; - if (hintView != null) { - // if an hint has been specified, we accomodate more space for it and - // add a text view in the drop down menu, at the bottom of the list - LinearLayout hintContainer = new LinearLayout(context); - hintContainer.setOrientation(LinearLayout.VERTICAL); - - LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f - ); - - switch (mPromptPosition) { - case POSITION_PROMPT_BELOW: - hintContainer.addView(dropDownView, hintParams); - hintContainer.addView(hintView); - break; - - case POSITION_PROMPT_ABOVE: - hintContainer.addView(hintView); - hintContainer.addView(dropDownView, hintParams); - break; - - default: - break; - } - - // measure the hint's height to find how much more vertical space - // we need to add to the drop down's height - int widthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.AT_MOST); - int heightSpec = MeasureSpec.UNSPECIFIED; - hintView.measure(widthSpec, heightSpec); - - hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams(); - otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin - + hintParams.bottomMargin; - - dropDownView = hintContainer; - } - - mPopup.setContentView(dropDownView); - } else { - dropDownView = (ViewGroup) mPopup.getContentView(); - final View view = mPromptView; - if (view != null) { - LinearLayout.LayoutParams hintParams = - (LinearLayout.LayoutParams) view.getLayoutParams(); - otherHeights = view.getMeasuredHeight() + hintParams.topMargin - + hintParams.bottomMargin; - } - } - - // getMaxAvailableHeight() subtracts the padding, so we put it back - // to get the available height for the whole window - int padding = 0; - Drawable background = mPopup.getBackground(); - if (background != null) { - background.getPadding(mTempRect); - padding = mTempRect.top + mTempRect.bottom; - - // If we don't have an explicit vertical offset, determine one from the window - // background so that content will line up. - if (!mDropDownVerticalOffsetSet) { - mDropDownVerticalOffset = -mTempRect.top; - } - } - - // Max height available on the screen for a popup. - boolean ignoreBottomDecorations = - mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; - final int maxHeight = /*mPopup.*/getMaxAvailableHeight( - mDropDownAnchorView, mDropDownVerticalOffset, ignoreBottomDecorations); - - if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { - return maxHeight + padding; - } - - final int listContent = /*mDropDownList.*/measureHeightOfChildren(MeasureSpec.UNSPECIFIED, - 0, -1/*ListView.NO_POSITION*/, maxHeight - otherHeights, -1); - // add padding only if the list has items in it, that way we don't show - // the popup if it is not needed - if (listContent > 0) otherHeights += padding; - - return listContent + otherHeights; - } - - private int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) { - final Rect displayFrame = new Rect(); - anchor.getWindowVisibleDisplayFrame(displayFrame); - - final int[] anchorPos = new int[2]; - anchor.getLocationOnScreen(anchorPos); - - int bottomEdge = displayFrame.bottom; - if (ignoreBottomDecorations) { - Resources res = anchor.getContext().getResources(); - bottomEdge = res.getDisplayMetrics().heightPixels; - } - final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset; - final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset; - - // anchorPos[1] is distance from anchor to top of screen - int returnedHeight = Math.max(distanceToBottom, distanceToTop); - if (mPopup.getBackground() != null) { - mPopup.getBackground().getPadding(mTempRect); - returnedHeight -= mTempRect.top + mTempRect.bottom; - } - - return returnedHeight; - } - - private int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, - final int maxHeight, int disallowPartialChildPosition) { - - final ListAdapter adapter = mAdapter; - if (adapter == null) { - return mDropDownList.getListPaddingTop() + mDropDownList.getListPaddingBottom(); - } - - // Include the padding of the list - int returnedHeight = mDropDownList.getListPaddingTop() + mDropDownList.getListPaddingBottom(); - final int dividerHeight = ((mDropDownList.getDividerHeight() > 0) && mDropDownList.getDivider() != null) ? mDropDownList.getDividerHeight() : 0; - // The previous height value that was less than maxHeight and contained - // no partial children - int prevHeightWithoutPartialChild = 0; - int i; - View child; - - // mItemCount - 1 since endPosition parameter is inclusive - endPosition = (endPosition == -1/*NO_POSITION*/) ? adapter.getCount() - 1 : endPosition; - - for (i = startPosition; i <= endPosition; ++i) { - child = mAdapter.getView(i, null, mDropDownList); - if (mDropDownList.getCacheColorHint() != 0) { - child.setDrawingCacheBackgroundColor(mDropDownList.getCacheColorHint()); - } - - measureScrapChild(child, i, widthMeasureSpec); - - if (i > 0) { - // Count the divider for all but one child - returnedHeight += dividerHeight; - } - - returnedHeight += child.getMeasuredHeight(); - - if (returnedHeight >= maxHeight) { - // We went over, figure out which height to return. If returnedHeight > maxHeight, - // then the i'th position did not fit completely. - return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) - && (i > disallowPartialChildPosition) // We've past the min pos - && (prevHeightWithoutPartialChild > 0) // We have a prev height - && (returnedHeight != maxHeight) // i'th child did not fit completely - ? prevHeightWithoutPartialChild - : maxHeight; - } - - if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { - prevHeightWithoutPartialChild = returnedHeight; - } - } - - // At this point, we went through the range of children, and they each - // completely fit, so return the returnedHeight - return returnedHeight; - } - private void measureScrapChild(View child, int position, int widthMeasureSpec) { - ListView.LayoutParams p = (ListView.LayoutParams) child.getLayoutParams(); - if (p == null) { - p = new ListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, 0); - child.setLayoutParams(p); - } - //XXX p.viewType = mAdapter.getItemViewType(position); - //XXX p.forceAdd = true; - - int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec, - mDropDownList.getPaddingLeft() + mDropDownList.getPaddingRight(), p.width); - int lpHeight = p.height; - int childHeightSpec; - if (lpHeight > 0) { - childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); - } else { - childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - } - child.measure(childWidthSpec, childHeightSpec); - } - - private static class DropDownListView extends ListView { - /* - * WARNING: This is a workaround for a touch mode issue. - * - * Touch mode is propagated lazily to windows. This causes problems in - * the following scenario: - * - Type something in the AutoCompleteTextView and get some results - * - Move down with the d-pad to select an item in the list - * - Move up with the d-pad until the selection disappears - * - Type more text in the AutoCompleteTextView *using the soft keyboard* - * and get new results; you are now in touch mode - * - The selection comes back on the first item in the list, even though - * the list is supposed to be in touch mode - * - * Using the soft keyboard triggers the touch mode change but that change - * is propagated to our window only after the first list layout, therefore - * after the list attempts to resurrect the selection. - * - * The trick to work around this issue is to pretend the list is in touch - * mode when we know that the selection should not appear, that is when - * we know the user moved the selection away from the list. - * - * This boolean is set to true whenever we explicitly hide the list's - * selection and reset to false whenever we know the user moved the - * selection back to the list. - * - * When this boolean is true, isInTouchMode() returns true, otherwise it - * returns super.isInTouchMode(). - */ - private boolean mListSelectionHidden; - - private boolean mHijackFocus; - - public DropDownListView(Context context, boolean hijackFocus) { - super(context, null, /*com.android.internal.*/R.attr.dropDownListViewStyle); - mHijackFocus = hijackFocus; - // TODO: Add an API to control this - setCacheColorHint(0); // Transparent, since the background drawable could be anything. - } - - //XXX @Override - //View obtainView(int position, boolean[] isScrap) { - // View view = super.obtainView(position, isScrap); - - // if (view instanceof TextView) { - // ((TextView) view).setHorizontallyScrolling(true); - // } - - // return view; - //} - - @Override - public boolean isInTouchMode() { - // WARNING: Please read the comment where mListSelectionHidden is declared - return (mHijackFocus && mListSelectionHidden) || super.isInTouchMode(); - } - - @Override - public boolean hasWindowFocus() { - return mHijackFocus || super.hasWindowFocus(); - } - - @Override - public boolean isFocused() { - return mHijackFocus || super.isFocused(); - } - - @Override - public boolean hasFocus() { - return mHijackFocus || super.hasFocus(); - } - } - - private class PopupDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - if (isShowing()) { - // Resize the popup to fit new content - show(); - } - } - - @Override - public void onInvalidated() { - dismiss(); - } - } - - private class ListSelectorHider implements Runnable { - public void run() { - clearListSelection(); - } - } - - private class ResizePopupRunnable implements Runnable { - public void run() { - if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() && - mDropDownList.getChildCount() <= mListItemExpandMaximum) { - mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); - show(); - } - } - } - - private class PopupTouchInterceptor implements OnTouchListener { - public boolean onTouch(View v, MotionEvent event) { - final int action = event.getAction(); - final int x = (int) event.getX(); - final int y = (int) event.getY(); - - if (action == MotionEvent.ACTION_DOWN && - mPopup != null && mPopup.isShowing() && - (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) { - mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT); - } else if (action == MotionEvent.ACTION_UP) { - mHandler.removeCallbacks(mResizePopupRunnable); - } - return false; - } - } - - private class PopupScrollListener implements ListView.OnScrollListener { - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, - int totalItemCount) { - - } - - public void onScrollStateChanged(AbsListView view, int scrollState) { - if (scrollState == SCROLL_STATE_TOUCH_SCROLL && - !isInputMethodNotNeeded() && mPopup.getContentView() != null) { - mHandler.removeCallbacks(mResizePopupRunnable); - mResizePopupRunnable.run(); - } - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java deleted file mode 100644 index 1c02d4aca..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java +++ /dev/null @@ -1,1193 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.BitmapShader; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.Shader; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.AnimationDrawable; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.ClipDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LayerDrawable; -import android.graphics.drawable.ShapeDrawable; -import android.graphics.drawable.shapes.RoundRectShape; -import android.graphics.drawable.shapes.Shape; -import android.os.Build; -import android.os.Parcel; -import android.os.Parcelable; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewDebug; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; -import android.view.animation.Transformation; -import android.widget.RemoteViews.RemoteView; - - -/** - *

- * Visual indicator of progress in some operation. Displays a bar to the user - * representing how far the operation has progressed; the application can - * change the amount of progress (modifying the length of the bar) as it moves - * forward. There is also a secondary progress displayable on a progress bar - * which is useful for displaying intermediate progress, such as the buffer - * level during a streaming playback progress bar. - *

- * - *

- * A progress bar can also be made indeterminate. In indeterminate mode, the - * progress bar shows a cyclic animation without an indication of progress. This mode is used by - * applications when the length of the task is unknown. The indeterminate progress bar can be either - * a spinning wheel or a horizontal bar. - *

- * - *

The following code example shows how a progress bar can be used from - * a worker thread to update the user interface to notify the user of progress: - *

- * - *
- * public class MyActivity extends Activity {
- *     private static final int PROGRESS = 0x1;
- *
- *     private ProgressBar mProgress;
- *     private int mProgressStatus = 0;
- *
- *     private Handler mHandler = new Handler();
- *
- *     protected void onCreate(Bundle icicle) {
- *         super.onCreate(icicle);
- *
- *         setContentView(R.layout.progressbar_activity);
- *
- *         mProgress = (ProgressBar) findViewById(R.id.progress_bar);
- *
- *         // Start lengthy operation in a background thread
- *         new Thread(new Runnable() {
- *             public void run() {
- *                 while (mProgressStatus < 100) {
- *                     mProgressStatus = doWork();
- *
- *                     // Update the progress bar
- *                     mHandler.post(new Runnable() {
- *                         public void run() {
- *                             mProgress.setProgress(mProgressStatus);
- *                         }
- *                     });
- *                 }
- *             }
- *         }).start();
- *     }
- * }
- * - *

To add a progress bar to a layout file, you can use the {@code <ProgressBar>} element. - * By default, the progress bar is a spinning wheel (an indeterminate indicator). To change to a - * horizontal progress bar, apply the {@link android.R.style#Widget_ProgressBar_Horizontal - * Widget.ProgressBar.Horizontal} style, like so:

- * - *
- * <ProgressBar
- *     style="@android:style/Widget.ProgressBar.Horizontal"
- *     ... />
- * - *

If you will use the progress bar to show real progress, you must use the horizontal bar. You - * can then increment the progress with {@link #incrementProgressBy incrementProgressBy()} or - * {@link #setProgress setProgress()}. By default, the progress bar is full when it reaches 100. If - * necessary, you can adjust the maximum value (the value for a full bar) using the {@link - * android.R.styleable#ProgressBar_max android:max} attribute. Other attributes available are listed - * below.

- * - *

Another common style to apply to the progress bar is {@link - * android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}, which shows a smaller - * version of the spinning wheel—useful when waiting for content to load. - * For example, you can insert this kind of progress bar into your default layout for - * a view that will be populated by some content fetched from the Internet—the spinning wheel - * appears immediately and when your application receives the content, it replaces the progress bar - * with the loaded content. For example:

- * - *
- * <LinearLayout
- *     android:orientation="horizontal"
- *     ... >
- *     <ProgressBar
- *         android:layout_width="wrap_content"
- *         android:layout_height="wrap_content"
- *         style="@android:style/Widget.ProgressBar.Small"
- *         android:layout_marginRight="5dp" />
- *     <TextView
- *         android:layout_width="wrap_content"
- *         android:layout_height="wrap_content"
- *         android:text="@string/loading" />
- * </LinearLayout>
- * - *

Other progress bar styles provided by the system include:

- *
    - *
  • {@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal}
  • - *
  • {@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}
  • - *
  • {@link android.R.style#Widget_ProgressBar_Large Widget.ProgressBar.Large}
  • - *
  • {@link android.R.style#Widget_ProgressBar_Inverse Widget.ProgressBar.Inverse}
  • - *
  • {@link android.R.style#Widget_ProgressBar_Small_Inverse - * Widget.ProgressBar.Small.Inverse}
  • - *
  • {@link android.R.style#Widget_ProgressBar_Large_Inverse - * Widget.ProgressBar.Large.Inverse}
  • - *
- *

The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary - * if your application uses a light colored theme (a white background).

- * - *

XML attributes - *

- * See {@link android.R.styleable#ProgressBar ProgressBar Attributes}, - * {@link android.R.styleable#View View Attributes} - *

- * - * @attr ref android.R.styleable#ProgressBar_animationResolution - * @attr ref android.R.styleable#ProgressBar_indeterminate - * @attr ref android.R.styleable#ProgressBar_indeterminateBehavior - * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable - * @attr ref android.R.styleable#ProgressBar_indeterminateDuration - * @attr ref android.R.styleable#ProgressBar_indeterminateOnly - * @attr ref android.R.styleable#ProgressBar_interpolator - * @attr ref android.R.styleable#ProgressBar_max - * @attr ref android.R.styleable#ProgressBar_maxHeight - * @attr ref android.R.styleable#ProgressBar_maxWidth - * @attr ref android.R.styleable#ProgressBar_minHeight - * @attr ref android.R.styleable#ProgressBar_minWidth - * @attr ref android.R.styleable#ProgressBar_progress - * @attr ref android.R.styleable#ProgressBar_progressDrawable - * @attr ref android.R.styleable#ProgressBar_secondaryProgress - */ -@RemoteView -public class IcsProgressBar extends View { - private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; - private static final int MAX_LEVEL = 10000; - private static final int ANIMATION_RESOLUTION = 200; - private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200; - - private static final int[] ProgressBar = new int[] { - android.R.attr.maxWidth, - android.R.attr.maxHeight, - android.R.attr.max, - android.R.attr.progress, - android.R.attr.secondaryProgress, - android.R.attr.indeterminate, - android.R.attr.indeterminateOnly, - android.R.attr.indeterminateDrawable, - android.R.attr.progressDrawable, - android.R.attr.indeterminateDuration, - android.R.attr.indeterminateBehavior, - android.R.attr.minWidth, - android.R.attr.minHeight, - android.R.attr.interpolator, - android.R.attr.animationResolution, - }; - private static final int ProgressBar_maxWidth = 0; - private static final int ProgressBar_maxHeight = 1; - private static final int ProgressBar_max = 2; - private static final int ProgressBar_progress = 3; - private static final int ProgressBar_secondaryProgress = 4; - private static final int ProgressBar_indeterminate = 5; - private static final int ProgressBar_indeterminateOnly = 6; - private static final int ProgressBar_indeterminateDrawable = 7; - private static final int ProgressBar_progressDrawable = 8; - private static final int ProgressBar_indeterminateDuration = 9; - private static final int ProgressBar_indeterminateBehavior = 10; - private static final int ProgressBar_minWidth = 11; - private static final int ProgressBar_minHeight = 12; - private static final int ProgressBar_interpolator = 13; - private static final int ProgressBar_animationResolution = 14; - - int mMinWidth; - int mMaxWidth; - int mMinHeight; - int mMaxHeight; - - private int mProgress; - private int mSecondaryProgress; - private int mMax; - - private int mBehavior; - private int mDuration; - private boolean mIndeterminate; - private boolean mOnlyIndeterminate; - private Transformation mTransformation; - private AlphaAnimation mAnimation; - private Drawable mIndeterminateDrawable; - private int mIndeterminateRealLeft; - private int mIndeterminateRealTop; - private Drawable mProgressDrawable; - private Drawable mCurrentDrawable; - Bitmap mSampleTile; - private boolean mNoInvalidate; - private Interpolator mInterpolator; - private RefreshProgressRunnable mRefreshProgressRunnable; - private long mUiThreadId; - private boolean mShouldStartAnimationDrawable; - private long mLastDrawTime; - - private boolean mInDrawing; - - private int mAnimationResolution; - - private AccessibilityManager mAccessibilityManager; - private AccessibilityEventSender mAccessibilityEventSender; - - /** - * Create a new progress bar with range 0...100 and initial progress of 0. - * @param context the application environment - */ - public IcsProgressBar(Context context) { - this(context, null); - } - - public IcsProgressBar(Context context, AttributeSet attrs) { - this(context, attrs, android.R.attr.progressBarStyle); - } - - public IcsProgressBar(Context context, AttributeSet attrs, int defStyle) { - this(context, attrs, defStyle, 0); - } - - /** - * @hide - */ - public IcsProgressBar(Context context, AttributeSet attrs, int defStyle, int styleRes) { - super(context, attrs, defStyle); - mUiThreadId = Thread.currentThread().getId(); - initProgressBar(); - - TypedArray a = - context.obtainStyledAttributes(attrs, /*R.styleable.*/ProgressBar, defStyle, styleRes); - - mNoInvalidate = true; - - Drawable drawable = a.getDrawable(/*R.styleable.*/ProgressBar_progressDrawable); - if (drawable != null) { - drawable = tileify(drawable, false); - // Calling this method can set mMaxHeight, make sure the corresponding - // XML attribute for mMaxHeight is read after calling this method - setProgressDrawable(drawable); - } - - - mDuration = a.getInt(/*R.styleable.*/ProgressBar_indeterminateDuration, mDuration); - - mMinWidth = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_minWidth, mMinWidth); - mMaxWidth = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_maxWidth, mMaxWidth); - mMinHeight = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_minHeight, mMinHeight); - mMaxHeight = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_maxHeight, mMaxHeight); - - mBehavior = a.getInt(/*R.styleable.*/ProgressBar_indeterminateBehavior, mBehavior); - - final int resID = a.getResourceId( - /*com.android.internal.R.styleable.*/ProgressBar_interpolator, - android.R.anim.linear_interpolator); // default to linear interpolator - if (resID > 0) { - setInterpolator(context, resID); - } - - setMax(a.getInt(/*R.styleable.*/ProgressBar_max, mMax)); - - setProgress(a.getInt(/*R.styleable.*/ProgressBar_progress, mProgress)); - - setSecondaryProgress( - a.getInt(/*R.styleable.*/ProgressBar_secondaryProgress, mSecondaryProgress)); - - drawable = a.getDrawable(/*R.styleable.*/ProgressBar_indeterminateDrawable); - if (drawable != null) { - drawable = tileifyIndeterminate(drawable); - setIndeterminateDrawable(drawable); - } - - mOnlyIndeterminate = a.getBoolean( - /*R.styleable.*/ProgressBar_indeterminateOnly, mOnlyIndeterminate); - - mNoInvalidate = false; - - setIndeterminate(mOnlyIndeterminate || a.getBoolean( - /*R.styleable.*/ProgressBar_indeterminate, mIndeterminate)); - - mAnimationResolution = a.getInteger(/*R.styleable.*/ProgressBar_animationResolution, - ANIMATION_RESOLUTION); - - a.recycle(); - - mAccessibilityManager = (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE); - } - - /** - * Converts a drawable to a tiled version of itself. It will recursively - * traverse layer and state list drawables. - */ - private Drawable tileify(Drawable drawable, boolean clip) { - - if (drawable instanceof LayerDrawable) { - LayerDrawable background = (LayerDrawable) drawable; - final int N = background.getNumberOfLayers(); - Drawable[] outDrawables = new Drawable[N]; - - for (int i = 0; i < N; i++) { - int id = background.getId(i); - outDrawables[i] = tileify(background.getDrawable(i), - (id == android.R.id.progress || id == android.R.id.secondaryProgress)); - } - - LayerDrawable newBg = new LayerDrawable(outDrawables); - - for (int i = 0; i < N; i++) { - newBg.setId(i, background.getId(i)); - } - - return newBg; - - }/* else if (drawable instanceof StateListDrawable) { - StateListDrawable in = (StateListDrawable) drawable; - StateListDrawable out = new StateListDrawable(); - int numStates = in.getStateCount(); - for (int i = 0; i < numStates; i++) { - out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip)); - } - return out; - - }*/ else if (drawable instanceof BitmapDrawable) { - final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap(); - if (mSampleTile == null) { - mSampleTile = tileBitmap; - } - - final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); - - final BitmapShader bitmapShader = new BitmapShader(tileBitmap, - Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); - shapeDrawable.getPaint().setShader(bitmapShader); - - return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT, - ClipDrawable.HORIZONTAL) : shapeDrawable; - } - - return drawable; - } - - Shape getDrawableShape() { - final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 }; - return new RoundRectShape(roundedCorners, null, null); - } - - /** - * Convert a AnimationDrawable for use as a barberpole animation. - * Each frame of the animation is wrapped in a ClipDrawable and - * given a tiling BitmapShader. - */ - private Drawable tileifyIndeterminate(Drawable drawable) { - if (drawable instanceof AnimationDrawable) { - AnimationDrawable background = (AnimationDrawable) drawable; - final int N = background.getNumberOfFrames(); - AnimationDrawable newBg = new AnimationDrawable(); - newBg.setOneShot(background.isOneShot()); - - for (int i = 0; i < N; i++) { - Drawable frame = tileify(background.getFrame(i), true); - frame.setLevel(10000); - newBg.addFrame(frame, background.getDuration(i)); - } - newBg.setLevel(10000); - drawable = newBg; - } - return drawable; - } - - /** - *

- * Initialize the progress bar's default values: - *

- *
    - *
  • progress = 0
  • - *
  • max = 100
  • - *
  • animation duration = 4000 ms
  • - *
  • indeterminate = false
  • - *
  • behavior = repeat
  • - *
- */ - private void initProgressBar() { - mMax = 100; - mProgress = 0; - mSecondaryProgress = 0; - mIndeterminate = false; - mOnlyIndeterminate = false; - mDuration = 4000; - mBehavior = AlphaAnimation.RESTART; - mMinWidth = 24; - mMaxWidth = 48; - mMinHeight = 24; - mMaxHeight = 48; - } - - /** - *

Indicate whether this progress bar is in indeterminate mode.

- * - * @return true if the progress bar is in indeterminate mode - */ - @ViewDebug.ExportedProperty(category = "progress") - public synchronized boolean isIndeterminate() { - return mIndeterminate; - } - - /** - *

Change the indeterminate mode for this progress bar. In indeterminate - * mode, the progress is ignored and the progress bar shows an infinite - * animation instead.

- * - * If this progress bar's style only supports indeterminate mode (such as the circular - * progress bars), then this will be ignored. - * - * @param indeterminate true to enable the indeterminate mode - */ - public synchronized void setIndeterminate(boolean indeterminate) { - if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) { - mIndeterminate = indeterminate; - - if (indeterminate) { - // swap between indeterminate and regular backgrounds - mCurrentDrawable = mIndeterminateDrawable; - startAnimation(); - } else { - mCurrentDrawable = mProgressDrawable; - stopAnimation(); - } - } - } - - /** - *

Get the drawable used to draw the progress bar in - * indeterminate mode.

- * - * @return a {@link android.graphics.drawable.Drawable} instance - * - * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable) - * @see #setIndeterminate(boolean) - */ - public Drawable getIndeterminateDrawable() { - return mIndeterminateDrawable; - } - - /** - *

Define the drawable used to draw the progress bar in - * indeterminate mode.

- * - * @param d the new drawable - * - * @see #getIndeterminateDrawable() - * @see #setIndeterminate(boolean) - */ - public void setIndeterminateDrawable(Drawable d) { - if (d != null) { - d.setCallback(this); - } - mIndeterminateDrawable = d; - if (mIndeterminate) { - mCurrentDrawable = d; - postInvalidate(); - } - } - - /** - *

Get the drawable used to draw the progress bar in - * progress mode.

- * - * @return a {@link android.graphics.drawable.Drawable} instance - * - * @see #setProgressDrawable(android.graphics.drawable.Drawable) - * @see #setIndeterminate(boolean) - */ - public Drawable getProgressDrawable() { - return mProgressDrawable; - } - - /** - *

Define the drawable used to draw the progress bar in - * progress mode.

- * - * @param d the new drawable - * - * @see #getProgressDrawable() - * @see #setIndeterminate(boolean) - */ - public void setProgressDrawable(Drawable d) { - boolean needUpdate; - if (mProgressDrawable != null && d != mProgressDrawable) { - mProgressDrawable.setCallback(null); - needUpdate = true; - } else { - needUpdate = false; - } - - if (d != null) { - d.setCallback(this); - - // Make sure the ProgressBar is always tall enough - int drawableHeight = d.getMinimumHeight(); - if (mMaxHeight < drawableHeight) { - mMaxHeight = drawableHeight; - requestLayout(); - } - } - mProgressDrawable = d; - if (!mIndeterminate) { - mCurrentDrawable = d; - postInvalidate(); - } - - if (needUpdate) { - updateDrawableBounds(getWidth(), getHeight()); - updateDrawableState(); - doRefreshProgress(android.R.id.progress, mProgress, false, false); - doRefreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false, false); - } - } - - /** - * @return The drawable currently used to draw the progress bar - */ - Drawable getCurrentDrawable() { - return mCurrentDrawable; - } - - @Override - protected boolean verifyDrawable(Drawable who) { - return who == mProgressDrawable || who == mIndeterminateDrawable - || super.verifyDrawable(who); - } - - @Override - public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - if (mProgressDrawable != null) mProgressDrawable.jumpToCurrentState(); - if (mIndeterminateDrawable != null) mIndeterminateDrawable.jumpToCurrentState(); - } - - @Override - public void postInvalidate() { - if (!mNoInvalidate) { - super.postInvalidate(); - } - } - - private class RefreshProgressRunnable implements Runnable { - - private int mId; - private int mProgress; - private boolean mFromUser; - - RefreshProgressRunnable(int id, int progress, boolean fromUser) { - mId = id; - mProgress = progress; - mFromUser = fromUser; - } - - public void run() { - doRefreshProgress(mId, mProgress, mFromUser, true); - // Put ourselves back in the cache when we are done - mRefreshProgressRunnable = this; - } - - public void setup(int id, int progress, boolean fromUser) { - mId = id; - mProgress = progress; - mFromUser = fromUser; - } - - } - - private synchronized void doRefreshProgress(int id, int progress, boolean fromUser, - boolean callBackToApp) { - float scale = mMax > 0 ? (float) progress / (float) mMax : 0; - final Drawable d = mCurrentDrawable; - if (d != null) { - Drawable progressDrawable = null; - - if (d instanceof LayerDrawable) { - progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id); - } - - final int level = (int) (scale * MAX_LEVEL); - (progressDrawable != null ? progressDrawable : d).setLevel(level); - } else { - invalidate(); - } - - if (callBackToApp && id == android.R.id.progress) { - onProgressRefresh(scale, fromUser); - } - } - - void onProgressRefresh(float scale, boolean fromUser) { - if (mAccessibilityManager.isEnabled()) { - scheduleAccessibilityEventSender(); - } - } - - private synchronized void refreshProgress(int id, int progress, boolean fromUser) { - if (mUiThreadId == Thread.currentThread().getId()) { - doRefreshProgress(id, progress, fromUser, true); - } else { - RefreshProgressRunnable r; - if (mRefreshProgressRunnable != null) { - // Use cached RefreshProgressRunnable if available - r = mRefreshProgressRunnable; - // Uncache it - mRefreshProgressRunnable = null; - r.setup(id, progress, fromUser); - } else { - // Make a new one - r = new RefreshProgressRunnable(id, progress, fromUser); - } - post(r); - } - } - - /** - *

Set the current progress to the specified value. Does not do anything - * if the progress bar is in indeterminate mode.

- * - * @param progress the new progress, between 0 and {@link #getMax()} - * - * @see #setIndeterminate(boolean) - * @see #isIndeterminate() - * @see #getProgress() - * @see #incrementProgressBy(int) - */ - public synchronized void setProgress(int progress) { - setProgress(progress, false); - } - - synchronized void setProgress(int progress, boolean fromUser) { - if (mIndeterminate) { - return; - } - - if (progress < 0) { - progress = 0; - } - - if (progress > mMax) { - progress = mMax; - } - - if (progress != mProgress) { - mProgress = progress; - refreshProgress(android.R.id.progress, mProgress, fromUser); - } - } - - /** - *

- * Set the current secondary progress to the specified value. Does not do - * anything if the progress bar is in indeterminate mode. - *

- * - * @param secondaryProgress the new secondary progress, between 0 and {@link #getMax()} - * @see #setIndeterminate(boolean) - * @see #isIndeterminate() - * @see #getSecondaryProgress() - * @see #incrementSecondaryProgressBy(int) - */ - public synchronized void setSecondaryProgress(int secondaryProgress) { - if (mIndeterminate) { - return; - } - - if (secondaryProgress < 0) { - secondaryProgress = 0; - } - - if (secondaryProgress > mMax) { - secondaryProgress = mMax; - } - - if (secondaryProgress != mSecondaryProgress) { - mSecondaryProgress = secondaryProgress; - refreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false); - } - } - - /** - *

Get the progress bar's current level of progress. Return 0 when the - * progress bar is in indeterminate mode.

- * - * @return the current progress, between 0 and {@link #getMax()} - * - * @see #setIndeterminate(boolean) - * @see #isIndeterminate() - * @see #setProgress(int) - * @see #setMax(int) - * @see #getMax() - */ - @ViewDebug.ExportedProperty(category = "progress") - public synchronized int getProgress() { - return mIndeterminate ? 0 : mProgress; - } - - /** - *

Get the progress bar's current level of secondary progress. Return 0 when the - * progress bar is in indeterminate mode.

- * - * @return the current secondary progress, between 0 and {@link #getMax()} - * - * @see #setIndeterminate(boolean) - * @see #isIndeterminate() - * @see #setSecondaryProgress(int) - * @see #setMax(int) - * @see #getMax() - */ - @ViewDebug.ExportedProperty(category = "progress") - public synchronized int getSecondaryProgress() { - return mIndeterminate ? 0 : mSecondaryProgress; - } - - /** - *

Return the upper limit of this progress bar's range.

- * - * @return a positive integer - * - * @see #setMax(int) - * @see #getProgress() - * @see #getSecondaryProgress() - */ - @ViewDebug.ExportedProperty(category = "progress") - public synchronized int getMax() { - return mMax; - } - - /** - *

Set the range of the progress bar to 0...max.

- * - * @param max the upper range of this progress bar - * - * @see #getMax() - * @see #setProgress(int) - * @see #setSecondaryProgress(int) - */ - public synchronized void setMax(int max) { - if (max < 0) { - max = 0; - } - if (max != mMax) { - mMax = max; - postInvalidate(); - - if (mProgress > max) { - mProgress = max; - } - refreshProgress(android.R.id.progress, mProgress, false); - } - } - - /** - *

Increase the progress bar's progress by the specified amount.

- * - * @param diff the amount by which the progress must be increased - * - * @see #setProgress(int) - */ - public synchronized final void incrementProgressBy(int diff) { - setProgress(mProgress + diff); - } - - /** - *

Increase the progress bar's secondary progress by the specified amount.

- * - * @param diff the amount by which the secondary progress must be increased - * - * @see #setSecondaryProgress(int) - */ - public synchronized final void incrementSecondaryProgressBy(int diff) { - setSecondaryProgress(mSecondaryProgress + diff); - } - - /** - *

Start the indeterminate progress animation.

- */ - void startAnimation() { - if (getVisibility() != VISIBLE) { - return; - } - - if (mIndeterminateDrawable instanceof Animatable) { - mShouldStartAnimationDrawable = true; - mAnimation = null; - } else { - if (mInterpolator == null) { - mInterpolator = new LinearInterpolator(); - } - - mTransformation = new Transformation(); - mAnimation = new AlphaAnimation(0.0f, 1.0f); - mAnimation.setRepeatMode(mBehavior); - mAnimation.setRepeatCount(Animation.INFINITE); - mAnimation.setDuration(mDuration); - mAnimation.setInterpolator(mInterpolator); - mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME); - } - postInvalidate(); - } - - /** - *

Stop the indeterminate progress animation.

- */ - void stopAnimation() { - mAnimation = null; - mTransformation = null; - if (mIndeterminateDrawable instanceof Animatable) { - ((Animatable) mIndeterminateDrawable).stop(); - mShouldStartAnimationDrawable = false; - } - postInvalidate(); - } - - /** - * Sets the acceleration curve for the indeterminate animation. - * The interpolator is loaded as a resource from the specified context. - * - * @param context The application environment - * @param resID The resource identifier of the interpolator to load - */ - public void setInterpolator(Context context, int resID) { - setInterpolator(AnimationUtils.loadInterpolator(context, resID)); - } - - /** - * Sets the acceleration curve for the indeterminate animation. - * Defaults to a linear interpolation. - * - * @param interpolator The interpolator which defines the acceleration curve - */ - public void setInterpolator(Interpolator interpolator) { - mInterpolator = interpolator; - } - - /** - * Gets the acceleration curve type for the indeterminate animation. - * - * @return the {@link Interpolator} associated to this animation - */ - public Interpolator getInterpolator() { - return mInterpolator; - } - - @Override - public void setVisibility(int v) { - if (getVisibility() != v) { - super.setVisibility(v); - - if (mIndeterminate) { - // let's be nice with the UI thread - if (v == GONE || v == INVISIBLE) { - stopAnimation(); - } else { - startAnimation(); - } - } - } - } - - @Override - protected void onVisibilityChanged(View changedView, int visibility) { - super.onVisibilityChanged(changedView, visibility); - - if (mIndeterminate) { - // let's be nice with the UI thread - if (visibility == GONE || visibility == INVISIBLE) { - stopAnimation(); - } else { - startAnimation(); - } - } - } - - @Override - public void invalidateDrawable(Drawable dr) { - if (!mInDrawing) { - if (verifyDrawable(dr)) { - final Rect dirty = dr.getBounds(); - final int scrollX = getScrollX() + getPaddingLeft(); - final int scrollY = getScrollY() + getPaddingTop(); - - invalidate(dirty.left + scrollX, dirty.top + scrollY, - dirty.right + scrollX, dirty.bottom + scrollY); - } else { - super.invalidateDrawable(dr); - } - } - } - - /** - * @hide - * - @Override - public int getResolvedLayoutDirection(Drawable who) { - return (who == mProgressDrawable || who == mIndeterminateDrawable) ? - getResolvedLayoutDirection() : super.getResolvedLayoutDirection(who); - } - */ - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - updateDrawableBounds(w, h); - } - - private void updateDrawableBounds(int w, int h) { - // onDraw will translate the canvas so we draw starting at 0,0 - int right = w - getPaddingRight() - getPaddingLeft(); - int bottom = h - getPaddingBottom() - getPaddingTop(); - int top = 0; - int left = 0; - - if (mIndeterminateDrawable != null) { - // Aspect ratio logic does not apply to AnimationDrawables - if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) { - // Maintain aspect ratio. Certain kinds of animated drawables - // get very confused otherwise. - final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth(); - final int intrinsicHeight = mIndeterminateDrawable.getIntrinsicHeight(); - final float intrinsicAspect = (float) intrinsicWidth / intrinsicHeight; - final float boundAspect = (float) w / h; - if (intrinsicAspect != boundAspect) { - if (boundAspect > intrinsicAspect) { - // New width is larger. Make it smaller to match height. - final int width = (int) (h * intrinsicAspect); - left = (w - width) / 2; - right = left + width; - } else { - // New height is larger. Make it smaller to match width. - final int height = (int) (w * (1 / intrinsicAspect)); - top = (h - height) / 2; - bottom = top + height; - } - } - } - mIndeterminateDrawable.setBounds(0, 0, right - left, bottom - top); - mIndeterminateRealLeft = left; - mIndeterminateRealTop = top; - } - - if (mProgressDrawable != null) { - mProgressDrawable.setBounds(0, 0, right, bottom); - } - } - - @Override - protected synchronized void onDraw(Canvas canvas) { - super.onDraw(canvas); - - Drawable d = mCurrentDrawable; - if (d != null) { - // Translate canvas so a indeterminate circular progress bar with padding - // rotates properly in its animation - canvas.save(); - canvas.translate(getPaddingLeft() + mIndeterminateRealLeft, getPaddingTop() + mIndeterminateRealTop); - long time = getDrawingTime(); - if (mAnimation != null) { - mAnimation.getTransformation(time, mTransformation); - float scale = mTransformation.getAlpha(); - try { - mInDrawing = true; - d.setLevel((int) (scale * MAX_LEVEL)); - } finally { - mInDrawing = false; - } - if (SystemClock.uptimeMillis() - mLastDrawTime >= mAnimationResolution) { - mLastDrawTime = SystemClock.uptimeMillis(); - postInvalidateDelayed(mAnimationResolution); - } - } - d.draw(canvas); - canvas.restore(); - if (mShouldStartAnimationDrawable && d instanceof Animatable) { - ((Animatable) d).start(); - mShouldStartAnimationDrawable = false; - } - } - } - - @Override - protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - Drawable d = mCurrentDrawable; - - int dw = 0; - int dh = 0; - if (d != null) { - dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth())); - dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight())); - } - updateDrawableState(); - dw += getPaddingLeft() + getPaddingRight(); - dh += getPaddingTop() + getPaddingBottom(); - - if (IS_HONEYCOMB) { - setMeasuredDimension(View.resolveSizeAndState(dw, widthMeasureSpec, 0), - View.resolveSizeAndState(dh, heightMeasureSpec, 0)); - } else { - setMeasuredDimension(View.resolveSize(dw, widthMeasureSpec), - View.resolveSize(dh, heightMeasureSpec)); - } - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - updateDrawableState(); - } - - private void updateDrawableState() { - int[] state = getDrawableState(); - - if (mProgressDrawable != null && mProgressDrawable.isStateful()) { - mProgressDrawable.setState(state); - } - - if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) { - mIndeterminateDrawable.setState(state); - } - } - - static class SavedState extends BaseSavedState { - int progress; - int secondaryProgress; - - /** - * Constructor called from {@link IcsProgressBar#onSaveInstanceState()} - */ - SavedState(Parcelable superState) { - super(superState); - } - - /** - * Constructor called from {@link #CREATOR} - */ - private SavedState(Parcel in) { - super(in); - progress = in.readInt(); - secondaryProgress = in.readInt(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeInt(progress); - out.writeInt(secondaryProgress); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } - - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; - } - - @Override - public Parcelable onSaveInstanceState() { - // Force our ancestor class to save its state - Parcelable superState = super.onSaveInstanceState(); - SavedState ss = new SavedState(superState); - - ss.progress = mProgress; - ss.secondaryProgress = mSecondaryProgress; - - return ss; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - SavedState ss = (SavedState) state; - super.onRestoreInstanceState(ss.getSuperState()); - - setProgress(ss.progress); - setSecondaryProgress(ss.secondaryProgress); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (mIndeterminate) { - startAnimation(); - } - } - - @Override - protected void onDetachedFromWindow() { - if (mIndeterminate) { - stopAnimation(); - } - if(mRefreshProgressRunnable != null) { - removeCallbacks(mRefreshProgressRunnable); - } - if (mAccessibilityEventSender != null) { - removeCallbacks(mAccessibilityEventSender); - } - // This should come after stopAnimation(), otherwise an invalidate message remains in the - // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation - super.onDetachedFromWindow(); - } - - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setItemCount(mMax); - event.setCurrentItemIndex(mProgress); - } - - /** - * Schedule a command for sending an accessibility event. - *
- * Note: A command is used to ensure that accessibility events - * are sent at most one in a given time frame to save - * system resources while the progress changes quickly. - */ - private void scheduleAccessibilityEventSender() { - if (mAccessibilityEventSender == null) { - mAccessibilityEventSender = new AccessibilityEventSender(); - } else { - removeCallbacks(mAccessibilityEventSender); - } - postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT); - } - - /** - * Command for sending an accessibility event. - */ - private class AccessibilityEventSender implements Runnable { - public void run() { - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java deleted file mode 100644 index 038d1e031..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.internal.widget; - -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; -import com.actionbarsherlock.R; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListAdapter; -import android.widget.ListView; -import android.widget.PopupWindow; -import android.widget.SpinnerAdapter; - - -/** - * A view that displays one child at a time and lets the user pick among them. - * The items in the Spinner come from the {@link Adapter} associated with - * this view. - * - *

See the Spinner - * tutorial.

- * - * @attr ref android.R.styleable#Spinner_prompt - */ -public class IcsSpinner extends IcsAbsSpinner implements OnClickListener { - //private static final String TAG = "Spinner"; - - // Only measure this many items to get a decent max width. - private static final int MAX_ITEMS_MEASURED = 15; - - /** - * Use a dialog window for selecting spinner options. - */ - //public static final int MODE_DIALOG = 0; - - /** - * Use a dropdown anchored to the Spinner for selecting spinner options. - */ - public static final int MODE_DROPDOWN = 1; - - /** - * Use the theme-supplied value to select the dropdown mode. - */ - //private static final int MODE_THEME = -1; - - private SpinnerPopup mPopup; - private DropDownAdapter mTempAdapter; - int mDropDownWidth; - - private int mGravity; - private boolean mDisableChildrenWhenDisabled; - - private Rect mTempRect = new Rect(); - - public IcsSpinner(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.actionDropDownStyle); - } - - /** - * Construct a new spinner with the given context's theme, the supplied attribute set, - * and default style. - * - * @param context The Context the view is running in, through which it can - * access the current theme, resources, etc. - * @param attrs The attributes of the XML tag that is inflating the view. - * @param defStyle The default style to apply to this view. If 0, no style - * will be applied (beyond what is included in the theme). This may - * either be an attribute resource, whose value will be retrieved - * from the current theme, or an explicit style resource. - */ - public IcsSpinner(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.SherlockSpinner, defStyle, 0); - - - DropdownPopup popup = new DropdownPopup(context, attrs, defStyle); - - mDropDownWidth = a.getLayoutDimension( - R.styleable.SherlockSpinner_android_dropDownWidth, - ViewGroup.LayoutParams.WRAP_CONTENT); - popup.setBackgroundDrawable(a.getDrawable( - R.styleable.SherlockSpinner_android_popupBackground)); - final int verticalOffset = a.getDimensionPixelOffset( - R.styleable.SherlockSpinner_android_dropDownVerticalOffset, 0); - if (verticalOffset != 0) { - popup.setVerticalOffset(verticalOffset); - } - - final int horizontalOffset = a.getDimensionPixelOffset( - R.styleable.SherlockSpinner_android_dropDownHorizontalOffset, 0); - if (horizontalOffset != 0) { - popup.setHorizontalOffset(horizontalOffset); - } - - mPopup = popup; - - mGravity = a.getInt(R.styleable.SherlockSpinner_android_gravity, Gravity.CENTER); - - mPopup.setPromptText(a.getString(R.styleable.SherlockSpinner_android_prompt)); - - mDisableChildrenWhenDisabled = true; - - a.recycle(); - - // Base constructor can call setAdapter before we initialize mPopup. - // Finish setting things up if this happened. - if (mTempAdapter != null) { - mPopup.setAdapter(mTempAdapter); - mTempAdapter = null; - } - } - - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (mDisableChildrenWhenDisabled) { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - getChildAt(i).setEnabled(enabled); - } - } - } - - /** - * Describes how the selected item view is positioned. Currently only the horizontal component - * is used. The default is determined by the current theme. - * - * @param gravity See {@link android.view.Gravity} - * - * @attr ref android.R.styleable#Spinner_gravity - */ - public void setGravity(int gravity) { - if (mGravity != gravity) { - if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) { - gravity |= Gravity.LEFT; - } - mGravity = gravity; - requestLayout(); - } - } - - @Override - public void setAdapter(SpinnerAdapter adapter) { - super.setAdapter(adapter); - - if (mPopup != null) { - mPopup.setAdapter(new DropDownAdapter(adapter)); - } else { - mTempAdapter = new DropDownAdapter(adapter); - } - } - - @Override - public int getBaseline() { - View child = null; - - if (getChildCount() > 0) { - child = getChildAt(0); - } else if (mAdapter != null && mAdapter.getCount() > 0) { - child = makeAndAddView(0); - mRecycler.put(0, child); - removeAllViewsInLayout(); - } - - if (child != null) { - final int childBaseline = child.getBaseline(); - return childBaseline >= 0 ? child.getTop() + childBaseline : -1; - } else { - return -1; - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - if (mPopup != null && mPopup.isShowing()) { - mPopup.dismiss(); - } - } - - /** - *

A spinner does not support item click events. Calling this method - * will raise an exception.

- * - * @param l this listener will be ignored - */ - @Override - public void setOnItemClickListener(OnItemClickListener l) { - throw new RuntimeException("setOnItemClickListener cannot be used with a spinner."); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { - final int measuredWidth = getMeasuredWidth(); - setMeasuredDimension(Math.min(Math.max(measuredWidth, - measureContentWidth(getAdapter(), getBackground())), - MeasureSpec.getSize(widthMeasureSpec)), - getMeasuredHeight()); - } - } - - /** - * @see android.view.View#onLayout(boolean,int,int,int,int) - * - * Creates and positions all views - * - */ - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - mInLayout = true; - layout(0, false); - mInLayout = false; - } - - /** - * Creates and positions all views for this Spinner. - * - * @param delta Change in the selected position. +1 moves selection is moving to the right, - * so views are scrolling to the left. -1 means selection is moving to the left. - */ - @Override - void layout(int delta, boolean animate) { - int childrenLeft = mSpinnerPadding.left; - int childrenWidth = getRight() - getLeft() - mSpinnerPadding.left - mSpinnerPadding.right; - - if (mDataChanged) { - handleDataChanged(); - } - - // Handle the empty set by removing all views - if (mItemCount == 0) { - resetList(); - return; - } - - if (mNextSelectedPosition >= 0) { - setSelectedPositionInt(mNextSelectedPosition); - } - - recycleAllViews(); - - // Clear out old views - removeAllViewsInLayout(); - - // Make selected view and position it - mFirstPosition = mSelectedPosition; - View sel = makeAndAddView(mSelectedPosition); - int width = sel.getMeasuredWidth(); - int selectedOffset = childrenLeft; - switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { - case Gravity.CENTER_HORIZONTAL: - selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2); - break; - case Gravity.RIGHT: - selectedOffset = childrenLeft + childrenWidth - width; - break; - } - sel.offsetLeftAndRight(selectedOffset); - - // Flush any cached views that did not get reused above - mRecycler.clear(); - - invalidate(); - - checkSelectionChanged(); - - mDataChanged = false; - mNeedSync = false; - setNextSelectedPositionInt(mSelectedPosition); - } - - /** - * Obtain a view, either by pulling an existing view from the recycler or - * by getting a new one from the adapter. If we are animating, make sure - * there is enough information in the view's layout parameters to animate - * from the old to new positions. - * - * @param position Position in the spinner for the view to obtain - * @return A view that has been added to the spinner - */ - private View makeAndAddView(int position) { - - View child; - - if (!mDataChanged) { - child = mRecycler.get(position); - if (child != null) { - // Position the view - setUpChild(child); - - return child; - } - } - - // Nothing found in the recycler -- ask the adapter for a view - child = mAdapter.getView(position, null, this); - - // Position the view - setUpChild(child); - - return child; - } - - /** - * Helper for makeAndAddView to set the position of a view - * and fill out its layout paramters. - * - * @param child The view to position - */ - private void setUpChild(View child) { - - // Respect layout params that are already in the view. Otherwise - // make some up... - ViewGroup.LayoutParams lp = child.getLayoutParams(); - if (lp == null) { - lp = generateDefaultLayoutParams(); - } - - addViewInLayout(child, 0, lp); - - child.setSelected(hasFocus()); - if (mDisableChildrenWhenDisabled) { - child.setEnabled(isEnabled()); - } - - // Get measure specs - int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, - mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height); - int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, - mSpinnerPadding.left + mSpinnerPadding.right, lp.width); - - // Measure child - child.measure(childWidthSpec, childHeightSpec); - - int childLeft; - int childRight; - - // Position vertically based on gravity setting - int childTop = mSpinnerPadding.top - + ((getMeasuredHeight() - mSpinnerPadding.bottom - - mSpinnerPadding.top - child.getMeasuredHeight()) / 2); - int childBottom = childTop + child.getMeasuredHeight(); - - int width = child.getMeasuredWidth(); - childLeft = 0; - childRight = childLeft + width; - - child.layout(childLeft, childTop, childRight, childBottom); - } - - @Override - public boolean performClick() { - boolean handled = super.performClick(); - - if (!handled) { - handled = true; - - if (!mPopup.isShowing()) { - mPopup.show(); - } - } - - return handled; - } - - public void onClick(DialogInterface dialog, int which) { - setSelection(which); - dialog.dismiss(); - } - - /** - * Sets the prompt to display when the dialog is shown. - * @param prompt the prompt to set - */ - public void setPrompt(CharSequence prompt) { - mPopup.setPromptText(prompt); - } - - /** - * Sets the prompt to display when the dialog is shown. - * @param promptId the resource ID of the prompt to display when the dialog is shown - */ - public void setPromptId(int promptId) { - setPrompt(getContext().getText(promptId)); - } - - /** - * @return The prompt to display when the dialog is shown - */ - public CharSequence getPrompt() { - return mPopup.getHintText(); - } - - int measureContentWidth(SpinnerAdapter adapter, Drawable background) { - if (adapter == null) { - return 0; - } - - int width = 0; - View itemView = null; - int itemType = 0; - final int widthMeasureSpec = - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int heightMeasureSpec = - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - - // Make sure the number of items we'll measure is capped. If it's a huge data set - // with wildly varying sizes, oh well. - int start = Math.max(0, getSelectedItemPosition()); - final int end = Math.min(adapter.getCount(), start + MAX_ITEMS_MEASURED); - final int count = end - start; - start = Math.max(0, start - (MAX_ITEMS_MEASURED - count)); - for (int i = start; i < end; i++) { - final int positionType = adapter.getItemViewType(i); - if (positionType != itemType) { - itemType = positionType; - itemView = null; - } - itemView = adapter.getView(i, itemView, this); - if (itemView.getLayoutParams() == null) { - itemView.setLayoutParams(new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT)); - } - itemView.measure(widthMeasureSpec, heightMeasureSpec); - width = Math.max(width, itemView.getMeasuredWidth()); - } - - // Add background padding to measured width - if (background != null) { - background.getPadding(mTempRect); - width += mTempRect.left + mTempRect.right; - } - - return width; - } - - /** - *

Wrapper class for an Adapter. Transforms the embedded Adapter instance - * into a ListAdapter.

- */ - private static class DropDownAdapter implements ListAdapter, SpinnerAdapter { - private SpinnerAdapter mAdapter; - private ListAdapter mListAdapter; - - /** - *

Creates a new ListAdapter wrapper for the specified adapter.

- * - * @param adapter the Adapter to transform into a ListAdapter - */ - public DropDownAdapter(SpinnerAdapter adapter) { - this.mAdapter = adapter; - if (adapter instanceof ListAdapter) { - this.mListAdapter = (ListAdapter) adapter; - } - } - - public int getCount() { - return mAdapter == null ? 0 : mAdapter.getCount(); - } - - public Object getItem(int position) { - return mAdapter == null ? null : mAdapter.getItem(position); - } - - public long getItemId(int position) { - return mAdapter == null ? -1 : mAdapter.getItemId(position); - } - - public View getView(int position, View convertView, ViewGroup parent) { - return getDropDownView(position, convertView, parent); - } - - public View getDropDownView(int position, View convertView, ViewGroup parent) { - return mAdapter == null ? null : - mAdapter.getDropDownView(position, convertView, parent); - } - - public boolean hasStableIds() { - return mAdapter != null && mAdapter.hasStableIds(); - } - - public void registerDataSetObserver(DataSetObserver observer) { - if (mAdapter != null) { - mAdapter.registerDataSetObserver(observer); - } - } - - public void unregisterDataSetObserver(DataSetObserver observer) { - if (mAdapter != null) { - mAdapter.unregisterDataSetObserver(observer); - } - } - - /** - * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call. - * Otherwise, return true. - */ - public boolean areAllItemsEnabled() { - final ListAdapter adapter = mListAdapter; - if (adapter != null) { - return adapter.areAllItemsEnabled(); - } else { - return true; - } - } - - /** - * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call. - * Otherwise, return true. - */ - public boolean isEnabled(int position) { - final ListAdapter adapter = mListAdapter; - if (adapter != null) { - return adapter.isEnabled(position); - } else { - return true; - } - } - - public int getItemViewType(int position) { - return 0; - } - - public int getViewTypeCount() { - return 1; - } - - public boolean isEmpty() { - return getCount() == 0; - } - } - - /** - * Implements some sort of popup selection interface for selecting a spinner option. - * Allows for different spinner modes. - */ - private interface SpinnerPopup { - public void setAdapter(ListAdapter adapter); - - /** - * Show the popup - */ - public void show(); - - /** - * Dismiss the popup - */ - public void dismiss(); - - /** - * @return true if the popup is showing, false otherwise. - */ - public boolean isShowing(); - - /** - * Set hint text to be displayed to the user. This should provide - * a description of the choice being made. - * @param hintText Hint text to set. - */ - public void setPromptText(CharSequence hintText); - public CharSequence getHintText(); - } - - /* - private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener { - private AlertDialog mPopup; - private ListAdapter mListAdapter; - private CharSequence mPrompt; - - public void dismiss() { - mPopup.dismiss(); - mPopup = null; - } - - public boolean isShowing() { - return mPopup != null ? mPopup.isShowing() : false; - } - - public void setAdapter(ListAdapter adapter) { - mListAdapter = adapter; - } - - public void setPromptText(CharSequence hintText) { - mPrompt = hintText; - } - - public CharSequence getHintText() { - return mPrompt; - } - - public void show() { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - if (mPrompt != null) { - builder.setTitle(mPrompt); - } - mPopup = builder.setSingleChoiceItems(mListAdapter, - getSelectedItemPosition(), this).show(); - } - - public void onClick(DialogInterface dialog, int which) { - setSelection(which); - dismiss(); - } - } - */ - - private class DropdownPopup extends IcsListPopupWindow implements SpinnerPopup { - private CharSequence mHintText; - private ListAdapter mAdapter; - - public DropdownPopup(Context context, AttributeSet attrs, int defStyleRes) { - super(context, attrs, 0, defStyleRes); - - setAnchorView(IcsSpinner.this); - setModal(true); - setPromptPosition(POSITION_PROMPT_ABOVE); - setOnItemClickListener(new OnItemClickListener() { - @SuppressWarnings("rawtypes") - public void onItemClick(AdapterView parent, View v, int position, long id) { - IcsSpinner.this.setSelection(position); - dismiss(); - } - }); - } - - @Override - public void setAdapter(ListAdapter adapter) { - super.setAdapter(adapter); - mAdapter = adapter; - } - - public CharSequence getHintText() { - return mHintText; - } - - public void setPromptText(CharSequence hintText) { - // Hint text is ignored for dropdowns, but maintain it here. - mHintText = hintText; - } - - @Override - public void show() { - final int spinnerPaddingLeft = IcsSpinner.this.getPaddingLeft(); - if (mDropDownWidth == WRAP_CONTENT) { - final int spinnerWidth = IcsSpinner.this.getWidth(); - final int spinnerPaddingRight = IcsSpinner.this.getPaddingRight(); - setContentWidth(Math.max( - measureContentWidth((SpinnerAdapter) mAdapter, getBackground()), - spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight)); - } else if (mDropDownWidth == MATCH_PARENT) { - final int spinnerWidth = IcsSpinner.this.getWidth(); - final int spinnerPaddingRight = IcsSpinner.this.getPaddingRight(); - setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight); - } else { - setContentWidth(mDropDownWidth); - } - final Drawable background = getBackground(); - int bgOffset = 0; - if (background != null) { - background.getPadding(mTempRect); - bgOffset = -mTempRect.left; - } - setHorizontalOffset(bgOffset + spinnerPaddingLeft); - setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); - super.show(); - getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); - setSelection(IcsSpinner.this.getSelectedItemPosition()); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java deleted file mode 100644 index a7185d082..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.actionbarsherlock.internal.widget; - -import android.view.View; - -final class IcsView { - //No instances - private IcsView() {} - - /** - * Return only the state bits of {@link #getMeasuredWidthAndState()} - * and {@link #getMeasuredHeightAndState()}, combined into one integer. - * The width component is in the regular bits {@link #MEASURED_STATE_MASK} - * and the height component is at the shifted bits - * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. - */ - public static int getMeasuredStateInt(View child) { - return (child.getMeasuredWidth()&View.MEASURED_STATE_MASK) - | ((child.getMeasuredHeight()>>View.MEASURED_HEIGHT_STATE_SHIFT) - & (View.MEASURED_STATE_MASK>>View.MEASURED_HEIGHT_STATE_SHIFT)); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java deleted file mode 100644 index 48fb5d8b4..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.actionbarsherlock.internal.widget; - -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.text.TextUtils.TruncateAt; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.widget.BaseAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ListView; -import com.actionbarsherlock.R; -import com.actionbarsherlock.app.ActionBar; -import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; -import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; -import com.actionbarsherlock.internal.nineoldandroids.widget.NineHorizontalScrollView; - -/** - * This widget implements the dynamic action bar tab behavior that can change - * across different configurations or circumstances. - */ -public class ScrollingTabContainerView extends NineHorizontalScrollView - implements IcsAdapterView.OnItemSelectedListener { - //UNUSED private static final String TAG = "ScrollingTabContainerView"; - Runnable mTabSelector; - private TabClickListener mTabClickListener; - - private IcsLinearLayout mTabLayout; - private IcsSpinner mTabSpinner; - private boolean mAllowCollapse; - - private LayoutInflater mInflater; - - int mMaxTabWidth; - private int mContentHeight; - private int mSelectedTabIndex; - - protected Animator mVisibilityAnim; - protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); - - private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator(); - - private static final int FADE_DURATION = 200; - - public ScrollingTabContainerView(Context context) { - super(context); - setHorizontalScrollBarEnabled(false); - - TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, - R.attr.actionBarStyle, 0); - setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); - a.recycle(); - - mInflater = LayoutInflater.from(context); - - mTabLayout = createTabLayout(); - addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY; - setFillViewport(lockedExpanded); - - final int childCount = mTabLayout.getChildCount(); - if (childCount > 1 && - (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { - if (childCount > 2) { - mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); - } else { - mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; - } - } else { - mMaxTabWidth = -1; - } - - heightMeasureSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY); - - final boolean canCollapse = !lockedExpanded && mAllowCollapse; - - if (canCollapse) { - // See if we should expand - mTabLayout.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec); - if (mTabLayout.getMeasuredWidth() > MeasureSpec.getSize(widthMeasureSpec)) { - performCollapse(); - } else { - performExpand(); - } - } else { - performExpand(); - } - - final int oldWidth = getMeasuredWidth(); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - final int newWidth = getMeasuredWidth(); - - if (lockedExpanded && oldWidth != newWidth) { - // Recenter the tab display if we're at a new (scrollable) size. - setTabSelected(mSelectedTabIndex); - } - } - - /** - * Indicates whether this view is collapsed into a dropdown menu instead - * of traditional tabs. - * @return true if showing as a spinner - */ - private boolean isCollapsed() { - return mTabSpinner != null && mTabSpinner.getParent() == this; - } - - public void setAllowCollapse(boolean allowCollapse) { - mAllowCollapse = allowCollapse; - } - - private void performCollapse() { - if (isCollapsed()) return; - - if (mTabSpinner == null) { - mTabSpinner = createSpinner(); - } - removeView(mTabLayout); - addView(mTabSpinner, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - if (mTabSpinner.getAdapter() == null) { - mTabSpinner.setAdapter(new TabAdapter()); - } - if (mTabSelector != null) { - removeCallbacks(mTabSelector); - mTabSelector = null; - } - mTabSpinner.setSelection(mSelectedTabIndex); - } - - private boolean performExpand() { - if (!isCollapsed()) return false; - - removeView(mTabSpinner); - addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.MATCH_PARENT)); - setTabSelected(mTabSpinner.getSelectedItemPosition()); - return false; - } - - public void setTabSelected(int position) { - mSelectedTabIndex = position; - final int tabCount = mTabLayout.getChildCount(); - for (int i = 0; i < tabCount; i++) { - final View child = mTabLayout.getChildAt(i); - final boolean isSelected = i == position; - child.setSelected(isSelected); - if (isSelected) { - animateToTab(position); - } - } - } - - public void setContentHeight(int contentHeight) { - mContentHeight = contentHeight; - requestLayout(); - } - - private IcsLinearLayout createTabLayout() { - final IcsLinearLayout tabLayout = (IcsLinearLayout) LayoutInflater.from(getContext()) - .inflate(R.layout.abs__action_bar_tab_bar_view, null); - tabLayout.setMeasureWithLargestChildEnabled(true); - tabLayout.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); - return tabLayout; - } - - private IcsSpinner createSpinner() { - final IcsSpinner spinner = new IcsSpinner(getContext(), null, - R.attr.actionDropDownStyle); - spinner.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); - spinner.setOnItemSelectedListener(this); - return spinner; - } - - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - // Action bar can change size on configuration changes. - // Reread the desired height from the theme-specified style. - TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, - R.attr.actionBarStyle, 0); - setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); - a.recycle(); - } - - public void animateToVisibility(int visibility) { - if (mVisibilityAnim != null) { - mVisibilityAnim.cancel(); - } - if (visibility == VISIBLE) { - if (getVisibility() != VISIBLE) { - setAlpha(0); - } - ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); - anim.setDuration(FADE_DURATION); - anim.setInterpolator(sAlphaInterpolator); - - anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); - anim.start(); - } else { - ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); - anim.setDuration(FADE_DURATION); - anim.setInterpolator(sAlphaInterpolator); - - anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); - anim.start(); - } - } - - public void animateToTab(final int position) { - final View tabView = mTabLayout.getChildAt(position); - if (mTabSelector != null) { - removeCallbacks(mTabSelector); - } - mTabSelector = new Runnable() { - public void run() { - final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; - smoothScrollTo(scrollPos, 0); - mTabSelector = null; - } - }; - post(mTabSelector); - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - if (mTabSelector != null) { - // Re-post the selector we saved - post(mTabSelector); - } - } - - @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mTabSelector != null) { - removeCallbacks(mTabSelector); - } - } - - private TabView createTabView(ActionBar.Tab tab, boolean forAdapter) { - //Workaround for not being able to pass a defStyle on pre-3.0 - final TabView tabView = (TabView)mInflater.inflate(R.layout.abs__action_bar_tab, null); - tabView.init(this, tab, forAdapter); - - if (forAdapter) { - tabView.setBackgroundDrawable(null); - tabView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, - mContentHeight)); - } else { - tabView.setFocusable(true); - - if (mTabClickListener == null) { - mTabClickListener = new TabClickListener(); - } - tabView.setOnClickListener(mTabClickListener); - } - return tabView; - } - - public void addTab(ActionBar.Tab tab, boolean setSelected) { - TabView tabView = createTabView(tab, false); - mTabLayout.addView(tabView, new IcsLinearLayout.LayoutParams(0, - LayoutParams.MATCH_PARENT, 1)); - if (mTabSpinner != null) { - ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); - } - if (setSelected) { - tabView.setSelected(true); - } - if (mAllowCollapse) { - requestLayout(); - } - } - - public void addTab(ActionBar.Tab tab, int position, boolean setSelected) { - final TabView tabView = createTabView(tab, false); - mTabLayout.addView(tabView, position, new IcsLinearLayout.LayoutParams( - 0, LayoutParams.MATCH_PARENT, 1)); - if (mTabSpinner != null) { - ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); - } - if (setSelected) { - tabView.setSelected(true); - } - if (mAllowCollapse) { - requestLayout(); - } - } - - public void updateTab(int position) { - ((TabView) mTabLayout.getChildAt(position)).update(); - if (mTabSpinner != null) { - ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); - } - if (mAllowCollapse) { - requestLayout(); - } - } - - public void removeTabAt(int position) { - mTabLayout.removeViewAt(position); - if (mTabSpinner != null) { - ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); - } - if (mAllowCollapse) { - requestLayout(); - } - } - - public void removeAllTabs() { - mTabLayout.removeAllViews(); - if (mTabSpinner != null) { - ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); - } - if (mAllowCollapse) { - requestLayout(); - } - } - - @Override - public void onItemSelected(IcsAdapterView parent, View view, int position, long id) { - TabView tabView = (TabView) view; - tabView.getTab().select(); - } - - @Override - public void onNothingSelected(IcsAdapterView parent) { - } - - public static class TabView extends LinearLayout { - private ScrollingTabContainerView mParent; - private ActionBar.Tab mTab; - private CapitalizingTextView mTextView; - private ImageView mIconView; - private View mCustomView; - - public TabView(Context context, AttributeSet attrs) { - //TODO super(context, null, R.attr.actionBarTabStyle); - super(context, attrs); - } - - public void init(ScrollingTabContainerView parent, ActionBar.Tab tab, boolean forList) { - mParent = parent; - mTab = tab; - - if (forList) { - setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - } - - update(); - } - - public void bindTab(ActionBar.Tab tab) { - mTab = tab; - update(); - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - // Re-measure if we went beyond our maximum size. - if (mParent.mMaxTabWidth > 0 && getMeasuredWidth() > mParent.mMaxTabWidth) { - super.onMeasure(MeasureSpec.makeMeasureSpec(mParent.mMaxTabWidth, MeasureSpec.EXACTLY), - heightMeasureSpec); - } - } - - public void update() { - final ActionBar.Tab tab = mTab; - final View custom = tab.getCustomView(); - if (custom != null) { - final ViewParent customParent = custom.getParent(); - if (customParent != this) { - if (customParent != null) ((ViewGroup) customParent).removeView(custom); - addView(custom); - } - mCustomView = custom; - if (mTextView != null) mTextView.setVisibility(GONE); - if (mIconView != null) { - mIconView.setVisibility(GONE); - mIconView.setImageDrawable(null); - } - } else { - if (mCustomView != null) { - removeView(mCustomView); - mCustomView = null; - } - - final Drawable icon = tab.getIcon(); - final CharSequence text = tab.getText(); - - if (icon != null) { - if (mIconView == null) { - ImageView iconView = new ImageView(getContext()); - LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - lp.gravity = Gravity.CENTER_VERTICAL; - iconView.setLayoutParams(lp); - addView(iconView, 0); - mIconView = iconView; - } - mIconView.setImageDrawable(icon); - mIconView.setVisibility(VISIBLE); - } else if (mIconView != null) { - mIconView.setVisibility(GONE); - mIconView.setImageDrawable(null); - } - - if (text != null) { - if (mTextView == null) { - CapitalizingTextView textView = new CapitalizingTextView(getContext(), null, - R.attr.actionBarTabTextStyle); - textView.setEllipsize(TruncateAt.END); - LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - lp.gravity = Gravity.CENTER_VERTICAL; - textView.setLayoutParams(lp); - addView(textView); - mTextView = textView; - } - mTextView.setTextCompat(text); - mTextView.setVisibility(VISIBLE); - } else if (mTextView != null) { - mTextView.setVisibility(GONE); - mTextView.setText(null); - } - - if (mIconView != null) { - mIconView.setContentDescription(tab.getContentDescription()); - } - } - } - - public ActionBar.Tab getTab() { - return mTab; - } - } - - private class TabAdapter extends BaseAdapter { - @Override - public int getCount() { - return mTabLayout.getChildCount(); - } - - @Override - public Object getItem(int position) { - return ((TabView) mTabLayout.getChildAt(position)).getTab(); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = createTabView((ActionBar.Tab) getItem(position), true); - } else { - ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position)); - } - return convertView; - } - } - - private class TabClickListener implements OnClickListener { - public void onClick(View view) { - TabView tabView = (TabView) view; - tabView.getTab().select(); - final int tabCount = mTabLayout.getChildCount(); - for (int i = 0; i < tabCount; i++) { - final View child = mTabLayout.getChildAt(i); - child.setSelected(child == view); - } - } - } - - protected class VisibilityAnimListener implements Animator.AnimatorListener { - private boolean mCanceled = false; - private int mFinalVisibility; - - public VisibilityAnimListener withFinalVisibility(int visibility) { - mFinalVisibility = visibility; - return this; - } - - @Override - public void onAnimationStart(Animator animation) { - setVisibility(VISIBLE); - mVisibilityAnim = animation; - mCanceled = false; - } - - @Override - public void onAnimationEnd(Animator animation) { - if (mCanceled) return; - - mVisibilityAnim = null; - setVisibility(mFinalVisibility); - } - - @Override - public void onAnimationCancel(Animator animation) { - mCanceled = true; - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java deleted file mode 100644 index 81b4cd4d2..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import android.view.View; - - -/** - * Represents a contextual mode of the user interface. Action modes can be used for - * modal interactions with content and replace parts of the normal UI until finished. - * Examples of good action modes include selection modes, search, content editing, etc. - */ -public abstract class ActionMode { - private Object mTag; - - /** - * Set a tag object associated with this ActionMode. - * - *

Like the tag available to views, this allows applications to associate arbitrary - * data with an ActionMode for later reference. - * - * @param tag Tag to associate with this ActionMode - * - * @see #getTag() - */ - public void setTag(Object tag) { - mTag = tag; - } - - /** - * Retrieve the tag object associated with this ActionMode. - * - *

Like the tag available to views, this allows applications to associate arbitrary - * data with an ActionMode for later reference. - * - * @return Tag associated with this ActionMode - * - * @see #setTag(Object) - */ - public Object getTag() { - return mTag; - } - - /** - * Set the title of the action mode. This method will have no visible effect if - * a custom view has been set. - * - * @param title Title string to set - * - * @see #setTitle(int) - * @see #setCustomView(View) - */ - public abstract void setTitle(CharSequence title); - - /** - * Set the title of the action mode. This method will have no visible effect if - * a custom view has been set. - * - * @param resId Resource ID of a string to set as the title - * - * @see #setTitle(CharSequence) - * @see #setCustomView(View) - */ - public abstract void setTitle(int resId); - - /** - * Set the subtitle of the action mode. This method will have no visible effect if - * a custom view has been set. - * - * @param subtitle Subtitle string to set - * - * @see #setSubtitle(int) - * @see #setCustomView(View) - */ - public abstract void setSubtitle(CharSequence subtitle); - - /** - * Set the subtitle of the action mode. This method will have no visible effect if - * a custom view has been set. - * - * @param resId Resource ID of a string to set as the subtitle - * - * @see #setSubtitle(CharSequence) - * @see #setCustomView(View) - */ - public abstract void setSubtitle(int resId); - - /** - * Set a custom view for this action mode. The custom view will take the place of - * the title and subtitle. Useful for things like search boxes. - * - * @param view Custom view to use in place of the title/subtitle. - * - * @see #setTitle(CharSequence) - * @see #setSubtitle(CharSequence) - */ - public abstract void setCustomView(View view); - - /** - * Invalidate the action mode and refresh menu content. The mode's - * {@link ActionMode.Callback} will have its - * {@link Callback#onPrepareActionMode(ActionMode, Menu)} method called. - * If it returns true the menu will be scanned for updated content and any relevant changes - * will be reflected to the user. - */ - public abstract void invalidate(); - - /** - * Finish and close this action mode. The action mode's {@link ActionMode.Callback} will - * have its {@link Callback#onDestroyActionMode(ActionMode)} method called. - */ - public abstract void finish(); - - /** - * Returns the menu of actions that this action mode presents. - * @return The action mode's menu. - */ - public abstract Menu getMenu(); - - /** - * Returns the current title of this action mode. - * @return Title text - */ - public abstract CharSequence getTitle(); - - /** - * Returns the current subtitle of this action mode. - * @return Subtitle text - */ - public abstract CharSequence getSubtitle(); - - /** - * Returns the current custom view for this action mode. - * @return The current custom view - */ - public abstract View getCustomView(); - - /** - * Returns a {@link MenuInflater} with the ActionMode's context. - */ - public abstract MenuInflater getMenuInflater(); - - /** - * Returns whether the UI presenting this action mode can take focus or not. - * This is used by internal components within the framework that would otherwise - * present an action mode UI that requires focus, such as an EditText as a custom view. - * - * @return true if the UI used to show this action mode can take focus - * @hide Internal use only - */ - public boolean isUiFocusable() { - return true; - } - - /** - * Callback interface for action modes. Supplied to - * {@link View#startActionMode(Callback)}, a Callback - * configures and handles events raised by a user's interaction with an action mode. - * - *

An action mode's lifecycle is as follows: - *

    - *
  • {@link Callback#onCreateActionMode(ActionMode, Menu)} once on initial - * creation
  • - *
  • {@link Callback#onPrepareActionMode(ActionMode, Menu)} after creation - * and any time the {@link ActionMode} is invalidated
  • - *
  • {@link Callback#onActionItemClicked(ActionMode, MenuItem)} any time a - * contextual action button is clicked
  • - *
  • {@link Callback#onDestroyActionMode(ActionMode)} when the action mode - * is closed
  • - *
- */ - public interface Callback { - /** - * Called when action mode is first created. The menu supplied will be used to - * generate action buttons for the action mode. - * - * @param mode ActionMode being created - * @param menu Menu used to populate action buttons - * @return true if the action mode should be created, false if entering this - * mode should be aborted. - */ - public boolean onCreateActionMode(ActionMode mode, Menu menu); - - /** - * Called to refresh an action mode's action menu whenever it is invalidated. - * - * @param mode ActionMode being prepared - * @param menu Menu used to populate action buttons - * @return true if the menu or action mode was updated, false otherwise. - */ - public boolean onPrepareActionMode(ActionMode mode, Menu menu); - - /** - * Called to report a user click on an action button. - * - * @param mode The current ActionMode - * @param item The item that was clicked - * @return true if this callback handled the event, false if the standard MenuItem - * invocation should continue. - */ - public boolean onActionItemClicked(ActionMode mode, MenuItem item); - - /** - * Called when an action mode is about to be exited and destroyed. - * - * @param mode The current ActionMode being destroyed - */ - public void onDestroyActionMode(ActionMode mode); - } -} \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java deleted file mode 100644 index ae7cb1fe0..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import android.content.Context; -import android.view.View; - -/** - * This class is a mediator for accomplishing a given task, for example sharing a file. - * It is responsible for creating a view that performs an action that accomplishes the task. - * This class also implements other functions such a performing a default action. - *

- * An ActionProvider can be optionally specified for a {@link MenuItem} and in such a - * case it will be responsible for creating the action view that appears in the - * {@link android.app.ActionBar} as a substitute for the menu item when the item is - * displayed as an action item. Also the provider is responsible for performing a - * default action if a menu item placed on the overflow menu of the ActionBar is - * selected and none of the menu item callbacks has handled the selection. For this - * case the provider can also optionally provide a sub-menu for accomplishing the - * task at hand. - *

- *

- * There are two ways for using an action provider for creating and handling of action views: - *

    - *
  • - * Setting the action provider on a {@link MenuItem} directly by calling - * {@link MenuItem#setActionProvider(ActionProvider)}. - *
  • - *
  • - * Declaring the action provider in the menu XML resource. For example: - *
    - * 
    - *   <item android:id="@+id/my_menu_item"
    - *     android:title="Title"
    - *     android:icon="@drawable/my_menu_item_icon"
    - *     android:showAsAction="ifRoom"
    - *     android:actionProviderClass="foo.bar.SomeActionProvider" />
    - * 
    - * 
    - *
  • - *
- *

- * - * @see MenuItem#setActionProvider(ActionProvider) - * @see MenuItem#getActionProvider() - */ -public abstract class ActionProvider { - private SubUiVisibilityListener mSubUiVisibilityListener; - - /** - * Creates a new instance. - * - * @param context Context for accessing resources. - */ - public ActionProvider(Context context) { - } - - /** - * Factory method for creating new action views. - * - * @return A new action view. - */ - public abstract View onCreateActionView(); - - /** - * Performs an optional default action. - *

- * For the case of an action provider placed in a menu item not shown as an action this - * method is invoked if previous callbacks for processing menu selection has handled - * the event. - *

- *

- * A menu item selection is processed in the following order: - *

    - *
  • - * Receiving a call to {@link MenuItem.OnMenuItemClickListener#onMenuItemClick - * MenuItem.OnMenuItemClickListener.onMenuItemClick}. - *
  • - *
  • - * Receiving a call to {@link android.app.Activity#onOptionsItemSelected(MenuItem) - * Activity.onOptionsItemSelected(MenuItem)} - *
  • - *
  • - * Receiving a call to {@link android.app.Fragment#onOptionsItemSelected(MenuItem) - * Fragment.onOptionsItemSelected(MenuItem)} - *
  • - *
  • - * Launching the {@link android.content.Intent} set via - * {@link MenuItem#setIntent(android.content.Intent) MenuItem.setIntent(android.content.Intent)} - *
  • - *
  • - * Invoking this method. - *
  • - *
- *

- *

- * The default implementation does not perform any action and returns false. - *

- */ - public boolean onPerformDefaultAction() { - return false; - } - - /** - * Determines if this ActionProvider has a submenu associated with it. - * - *

Associated submenus will be shown when an action view is not. This - * provider instance will receive a call to {@link #onPrepareSubMenu(SubMenu)} - * after the call to {@link #onPerformDefaultAction()} and before a submenu is - * displayed to the user. - * - * @return true if the item backed by this provider should have an associated submenu - */ - public boolean hasSubMenu() { - return false; - } - - /** - * Called to prepare an associated submenu for the menu item backed by this ActionProvider. - * - *

if {@link #hasSubMenu()} returns true, this method will be called when the - * menu item is selected to prepare the submenu for presentation to the user. Apps - * may use this to create or alter submenu content right before display. - * - * @param subMenu Submenu that will be displayed - */ - public void onPrepareSubMenu(SubMenu subMenu) { - } - - /** - * Notify the system that the visibility of an action view's sub-UI such as - * an anchored popup has changed. This will affect how other system - * visibility notifications occur. - * - * @hide Pending future API approval - */ - public void subUiVisibilityChanged(boolean isVisible) { - if (mSubUiVisibilityListener != null) { - mSubUiVisibilityListener.onSubUiVisibilityChanged(isVisible); - } - } - - /** - * @hide Internal use only - */ - public void setSubUiVisibilityListener(SubUiVisibilityListener listener) { - mSubUiVisibilityListener = listener; - } - - /** - * @hide Internal use only - */ - public interface SubUiVisibilityListener { - public void onSubUiVisibilityChanged(boolean isVisible); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java deleted file mode 100644 index 43281b013..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -/** - * When a {@link View} implements this interface it will receive callbacks - * when expanded or collapsed as an action view alongside the optional, - * app-specified callbacks to {@link OnActionExpandListener}. - * - *

See {@link MenuItem} for more information about action views. - * See {@link android.app.ActionBar} for more information about the action bar. - */ -public interface CollapsibleActionView { - /** - * Called when this view is expanded as an action view. - * See {@link MenuItem#expandActionView()}. - */ - public void onActionViewExpanded(); - - /** - * Called when this view is collapsed as an action view. - * See {@link MenuItem#collapseActionView()}. - */ - public void onActionViewCollapsed(); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java deleted file mode 100644 index 951f4ccef..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import android.content.ComponentName; -import android.content.Intent; -import android.view.KeyEvent; - -/** - * Interface for managing the items in a menu. - *

- * By default, every Activity supports an options menu of actions or options. - * You can add items to this menu and handle clicks on your additions. The - * easiest way of adding menu items is inflating an XML file into the - * {@link Menu} via {@link MenuInflater}. The easiest way of attaching code to - * clicks is via {@link Activity#onOptionsItemSelected(MenuItem)} and - * {@link Activity#onContextItemSelected(MenuItem)}. - *

- * Different menu types support different features: - *

    - *
  1. Context menus: Do not support item shortcuts and item icons. - *
  2. Options menus: The icon menus do not support item check - * marks and only show the item's - * {@link MenuItem#setTitleCondensed(CharSequence) condensed title}. The - * expanded menus (only available if six or more menu items are visible, - * reached via the 'More' item in the icon menu) do not show item icons, and - * item check marks are discouraged. - *
  3. Sub menus: Do not support item icons, or nested sub menus. - *
- * - *
- *

Developer Guides

- *

For more information about creating menus, read the - * Menus developer guide.

- *
- */ -public interface Menu { - - /** - * This is the part of an order integer that the user can provide. - * @hide - */ - static final int USER_MASK = 0x0000ffff; - /** - * Bit shift of the user portion of the order integer. - * @hide - */ - static final int USER_SHIFT = 0; - - /** - * This is the part of an order integer that supplies the category of the - * item. - * @hide - */ - static final int CATEGORY_MASK = 0xffff0000; - /** - * Bit shift of the category portion of the order integer. - * @hide - */ - static final int CATEGORY_SHIFT = 16; - - /** - * Value to use for group and item identifier integers when you don't care - * about them. - */ - static final int NONE = 0; - - /** - * First value for group and item identifier integers. - */ - static final int FIRST = 1; - - // Implementation note: Keep these CATEGORY_* in sync with the category enum - // in attrs.xml - - /** - * Category code for the order integer for items/groups that are part of a - * container -- or/add this with your base value. - */ - static final int CATEGORY_CONTAINER = 0x00010000; - - /** - * Category code for the order integer for items/groups that are provided by - * the system -- or/add this with your base value. - */ - static final int CATEGORY_SYSTEM = 0x00020000; - - /** - * Category code for the order integer for items/groups that are - * user-supplied secondary (infrequently used) options -- or/add this with - * your base value. - */ - static final int CATEGORY_SECONDARY = 0x00030000; - - /** - * Category code for the order integer for items/groups that are - * alternative actions on the data that is currently displayed -- or/add - * this with your base value. - */ - static final int CATEGORY_ALTERNATIVE = 0x00040000; - - /** - * Flag for {@link #addIntentOptions}: if set, do not automatically remove - * any existing menu items in the same group. - */ - static final int FLAG_APPEND_TO_GROUP = 0x0001; - - /** - * Flag for {@link #performShortcut}: if set, do not close the menu after - * executing the shortcut. - */ - static final int FLAG_PERFORM_NO_CLOSE = 0x0001; - - /** - * Flag for {@link #performShortcut(int, KeyEvent, int)}: if set, always - * close the menu after executing the shortcut. Closing the menu also resets - * the prepared state. - */ - static final int FLAG_ALWAYS_PERFORM_CLOSE = 0x0002; - - /** - * Add a new item to the menu. This item displays the given title for its - * label. - * - * @param title The text to display for the item. - * @return The newly added menu item. - */ - public MenuItem add(CharSequence title); - - /** - * Add a new item to the menu. This item displays the given title for its - * label. - * - * @param titleRes Resource identifier of title string. - * @return The newly added menu item. - */ - public MenuItem add(int titleRes); - - /** - * Add a new item to the menu. This item displays the given title for its - * label. - * - * @param groupId The group identifier that this item should be part of. - * This can be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a - * group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care - * about the order. See {@link MenuItem#getOrder()}. - * @param title The text to display for the item. - * @return The newly added menu item. - */ - public MenuItem add(int groupId, int itemId, int order, CharSequence title); - - /** - * Variation on {@link #add(int, int, int, CharSequence)} that takes a - * string resource identifier instead of the string itself. - * - * @param groupId The group identifier that this item should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a - * group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care - * about the order. See {@link MenuItem#getOrder()}. - * @param titleRes Resource identifier of title string. - * @return The newly added menu item. - */ - public MenuItem add(int groupId, int itemId, int order, int titleRes); - - /** - * Add a new sub-menu to the menu. This item displays the given title for - * its label. To modify other attributes on the submenu's menu item, use - * {@link SubMenu#getItem()}. - * - * @param title The text to display for the item. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(final CharSequence title); - - /** - * Add a new sub-menu to the menu. This item displays the given title for - * its label. To modify other attributes on the submenu's menu item, use - * {@link SubMenu#getItem()}. - * - * @param titleRes Resource identifier of title string. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(final int titleRes); - - /** - * Add a new sub-menu to the menu. This item displays the given - * title for its label. To modify other attributes on the - * submenu's menu item, use {@link SubMenu#getItem()}. - *

- * Note that you can only have one level of sub-menus, i.e. you cannnot add - * a subMenu to a subMenu: An {@link UnsupportedOperationException} will be - * thrown if you try. - * - * @param groupId The group identifier that this item should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a - * group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care - * about the order. See {@link MenuItem#getOrder()}. - * @param title The text to display for the item. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(final int groupId, final int itemId, int order, final CharSequence title); - - /** - * Variation on {@link #addSubMenu(int, int, int, CharSequence)} that takes - * a string resource identifier for the title instead of the string itself. - * - * @param groupId The group identifier that this item should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if an item should not be in a group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a unique ID. - * @param order The order for the item. Use {@link #NONE} if you do not care about the - * order. See {@link MenuItem#getOrder()}. - * @param titleRes Resource identifier of title string. - * @return The newly added sub-menu - */ - SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes); - - /** - * Add a group of menu items corresponding to actions that can be performed - * for a particular Intent. The Intent is most often configured with a null - * action, the data that the current activity is working with, and includes - * either the {@link Intent#CATEGORY_ALTERNATIVE} or - * {@link Intent#CATEGORY_SELECTED_ALTERNATIVE} to find activities that have - * said they would like to be included as optional action. You can, however, - * use any Intent you want. - * - *

- * See {@link android.content.pm.PackageManager#queryIntentActivityOptions} - * for more * details on the caller, specifics, and - * intent arguments. The list returned by that function is used - * to populate the resulting menu items. - * - *

- * All of the menu items of possible options for the intent will be added - * with the given group and id. You can use the group to control ordering of - * the items in relation to other items in the menu. Normally this function - * will automatically remove any existing items in the menu in the same - * group and place a divider above and below the added items; this behavior - * can be modified with the flags parameter. For each of the - * generated items {@link MenuItem#setIntent} is called to associate the - * appropriate Intent with the item; this means the activity will - * automatically be started for you without having to do anything else. - * - * @param groupId The group identifier that the items should be part of. - * This can also be used to define groups of items for batch state - * changes. Normally use {@link #NONE} if the items should not be in - * a group. - * @param itemId Unique item ID. Use {@link #NONE} if you do not need a - * unique ID. - * @param order The order for the items. Use {@link #NONE} if you do not - * care about the order. See {@link MenuItem#getOrder()}. - * @param caller The current activity component name as defined by - * queryIntentActivityOptions(). - * @param specifics Specific items to place first as defined by - * queryIntentActivityOptions(). - * @param intent Intent describing the kinds of items to populate in the - * list as defined by queryIntentActivityOptions(). - * @param flags Additional options controlling how the items are added. - * @param outSpecificItems Optional array in which to place the menu items - * that were generated for each of the specifics that were - * requested. Entries may be null if no activity was found for that - * specific action. - * @return The number of menu items that were added. - * - * @see #FLAG_APPEND_TO_GROUP - * @see MenuItem#setIntent - * @see android.content.pm.PackageManager#queryIntentActivityOptions - */ - public int addIntentOptions(int groupId, int itemId, int order, - ComponentName caller, Intent[] specifics, - Intent intent, int flags, MenuItem[] outSpecificItems); - - /** - * Remove the item with the given identifier. - * - * @param id The item to be removed. If there is no item with this - * identifier, nothing happens. - */ - public void removeItem(int id); - - /** - * Remove all items in the given group. - * - * @param groupId The group to be removed. If there are no items in this - * group, nothing happens. - */ - public void removeGroup(int groupId); - - /** - * Remove all existing items from the menu, leaving it empty as if it had - * just been created. - */ - public void clear(); - - /** - * Control whether a particular group of items can show a check mark. This - * is similar to calling {@link MenuItem#setCheckable} on all of the menu items - * with the given group identifier, but in addition you can control whether - * this group contains a mutually-exclusive set items. This should be called - * after the items of the group have been added to the menu. - * - * @param group The group of items to operate on. - * @param checkable Set to true to allow a check mark, false to - * disallow. The default is false. - * @param exclusive If set to true, only one item in this group can be - * checked at a time; checking an item will automatically - * uncheck all others in the group. If set to false, each - * item can be checked independently of the others. - * - * @see MenuItem#setCheckable - * @see MenuItem#setChecked - */ - public void setGroupCheckable(int group, boolean checkable, boolean exclusive); - - /** - * Show or hide all menu items that are in the given group. - * - * @param group The group of items to operate on. - * @param visible If true the items are visible, else they are hidden. - * - * @see MenuItem#setVisible - */ - public void setGroupVisible(int group, boolean visible); - - /** - * Enable or disable all menu items that are in the given group. - * - * @param group The group of items to operate on. - * @param enabled If true the items will be enabled, else they will be disabled. - * - * @see MenuItem#setEnabled - */ - public void setGroupEnabled(int group, boolean enabled); - - /** - * Return whether the menu currently has item items that are visible. - * - * @return True if there is one or more item visible, - * else false. - */ - public boolean hasVisibleItems(); - - /** - * Return the menu item with a particular identifier. - * - * @param id The identifier to find. - * - * @return The menu item object, or null if there is no item with - * this identifier. - */ - public MenuItem findItem(int id); - - /** - * Get the number of items in the menu. Note that this will change any - * times items are added or removed from the menu. - * - * @return The item count. - */ - public int size(); - - /** - * Gets the menu item at the given index. - * - * @param index The index of the menu item to return. - * @return The menu item. - * @exception IndexOutOfBoundsException - * when {@code index < 0 || >= size()} - */ - public MenuItem getItem(int index); - - /** - * Closes the menu, if open. - */ - public void close(); - - /** - * Execute the menu item action associated with the given shortcut - * character. - * - * @param keyCode The keycode of the shortcut key. - * @param event Key event message. - * @param flags Additional option flags or 0. - * - * @return If the given shortcut exists and is shown, returns - * true; else returns false. - * - * @see #FLAG_PERFORM_NO_CLOSE - */ - public boolean performShortcut(int keyCode, KeyEvent event, int flags); - - /** - * Is a keypress one of the defined shortcut keys for this window. - * @param keyCode the key code from {@link KeyEvent} to check. - * @param event the {@link KeyEvent} to use to help check. - */ - boolean isShortcutKey(int keyCode, KeyEvent event); - - /** - * Execute the menu item action associated with the given menu identifier. - * - * @param id Identifier associated with the menu item. - * @param flags Additional option flags or 0. - * - * @return If the given identifier exists and is shown, returns - * true; else returns false. - * - * @see #FLAG_PERFORM_NO_CLOSE - */ - public boolean performIdentifierAction(int id, int flags); - - - /** - * Control whether the menu should be running in qwerty mode (alphabetic - * shortcuts) or 12-key mode (numeric shortcuts). - * - * @param isQwerty If true the menu will use alphabetic shortcuts; else it - * will use numeric shortcuts. - */ - public void setQwertyMode(boolean isQwerty); -} - diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java deleted file mode 100644 index 5a0f40859..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * 2011 Jake Wharton - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import android.content.Context; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; -import android.util.Xml; -import android.view.InflateException; -import android.view.View; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.view.menu.MenuItemImpl; - -/** - * This class is used to instantiate menu XML files into Menu objects. - *

- * For performance reasons, menu inflation relies heavily on pre-processing of - * XML files that is done at build time. Therefore, it is not currently possible - * to use MenuInflater with an XmlPullParser over a plain XML file at runtime; - * it only works with an XmlPullParser returned from a compiled resource (R. - * something file.) - */ -public class MenuInflater { - private static final String LOG_TAG = "MenuInflater"; - - /** Menu tag name in XML. */ - private static final String XML_MENU = "menu"; - - /** Group tag name in XML. */ - private static final String XML_GROUP = "group"; - - /** Item tag name in XML. */ - private static final String XML_ITEM = "item"; - - private static final int NO_ID = 0; - - private static final Class[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[] {Context.class}; - - private static final Class[] ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE = ACTION_VIEW_CONSTRUCTOR_SIGNATURE; - - private final Object[] mActionViewConstructorArguments; - - private final Object[] mActionProviderConstructorArguments; - - private Context mContext; - private Object mRealOwner; - - /** - * Constructs a menu inflater. - * - * @see Activity#getMenuInflater() - */ - public MenuInflater(Context context) { - mContext = context; - mRealOwner = context; - mActionViewConstructorArguments = new Object[] {context}; - mActionProviderConstructorArguments = mActionViewConstructorArguments; - } - - /** - * Constructs a menu inflater. - * - * @see Activity#getMenuInflater() - * @hide - */ - public MenuInflater(Context context, Object realOwner) { - mContext = context; - mRealOwner = realOwner; - mActionViewConstructorArguments = new Object[] {context}; - mActionProviderConstructorArguments = mActionViewConstructorArguments; - } - - /** - * Inflate a menu hierarchy from the specified XML resource. Throws - * {@link InflateException} if there is an error. - * - * @param menuRes Resource ID for an XML layout resource to load (e.g., - * R.menu.main_activity) - * @param menu The Menu to inflate into. The items and submenus will be - * added to this Menu. - */ - public void inflate(int menuRes, Menu menu) { - XmlResourceParser parser = null; - try { - parser = mContext.getResources().getLayout(menuRes); - AttributeSet attrs = Xml.asAttributeSet(parser); - - parseMenu(parser, attrs, menu); - } catch (XmlPullParserException e) { - throw new InflateException("Error inflating menu XML", e); - } catch (IOException e) { - throw new InflateException("Error inflating menu XML", e); - } finally { - if (parser != null) parser.close(); - } - } - - /** - * Called internally to fill the given menu. If a sub menu is seen, it will - * call this recursively. - */ - private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu) - throws XmlPullParserException, IOException { - MenuState menuState = new MenuState(menu); - - int eventType = parser.getEventType(); - String tagName; - boolean lookingForEndOfUnknownTag = false; - String unknownTagName = null; - - // This loop will skip to the menu start tag - do { - if (eventType == XmlPullParser.START_TAG) { - tagName = parser.getName(); - if (tagName.equals(XML_MENU)) { - // Go to next tag - eventType = parser.next(); - break; - } - - throw new RuntimeException("Expecting menu, got " + tagName); - } - eventType = parser.next(); - } while (eventType != XmlPullParser.END_DOCUMENT); - - boolean reachedEndOfMenu = false; - while (!reachedEndOfMenu) { - switch (eventType) { - case XmlPullParser.START_TAG: - if (lookingForEndOfUnknownTag) { - break; - } - - tagName = parser.getName(); - if (tagName.equals(XML_GROUP)) { - menuState.readGroup(attrs); - } else if (tagName.equals(XML_ITEM)) { - menuState.readItem(attrs); - } else if (tagName.equals(XML_MENU)) { - // A menu start tag denotes a submenu for an item - SubMenu subMenu = menuState.addSubMenuItem(); - - // Parse the submenu into returned SubMenu - parseMenu(parser, attrs, subMenu); - } else { - lookingForEndOfUnknownTag = true; - unknownTagName = tagName; - } - break; - - case XmlPullParser.END_TAG: - tagName = parser.getName(); - if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) { - lookingForEndOfUnknownTag = false; - unknownTagName = null; - } else if (tagName.equals(XML_GROUP)) { - menuState.resetGroup(); - } else if (tagName.equals(XML_ITEM)) { - // Add the item if it hasn't been added (if the item was - // a submenu, it would have been added already) - if (!menuState.hasAddedItem()) { - if (menuState.itemActionProvider != null && - menuState.itemActionProvider.hasSubMenu()) { - menuState.addSubMenuItem(); - } else { - menuState.addItem(); - } - } - } else if (tagName.equals(XML_MENU)) { - reachedEndOfMenu = true; - } - break; - - case XmlPullParser.END_DOCUMENT: - throw new RuntimeException("Unexpected end of document"); - } - - eventType = parser.next(); - } - } - - private static class InflatedOnMenuItemClickListener - implements MenuItem.OnMenuItemClickListener { - private static final Class[] PARAM_TYPES = new Class[] { MenuItem.class }; - - private Object mRealOwner; - private Method mMethod; - - public InflatedOnMenuItemClickListener(Object realOwner, String methodName) { - mRealOwner = realOwner; - Class c = realOwner.getClass(); - try { - mMethod = c.getMethod(methodName, PARAM_TYPES); - } catch (Exception e) { - InflateException ex = new InflateException( - "Couldn't resolve menu item onClick handler " + methodName + - " in class " + c.getName()); - ex.initCause(e); - throw ex; - } - } - - public boolean onMenuItemClick(MenuItem item) { - try { - if (mMethod.getReturnType() == Boolean.TYPE) { - return (Boolean) mMethod.invoke(mRealOwner, item); - } else { - mMethod.invoke(mRealOwner, item); - return true; - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - /** - * State for the current menu. - *

- * Groups can not be nested unless there is another menu (which will have - * its state class). - */ - private class MenuState { - private Menu menu; - - /* - * Group state is set on items as they are added, allowing an item to - * override its group state. (As opposed to set on items at the group end tag.) - */ - private int groupId; - private int groupCategory; - private int groupOrder; - private int groupCheckable; - private boolean groupVisible; - private boolean groupEnabled; - - private boolean itemAdded; - private int itemId; - private int itemCategoryOrder; - private CharSequence itemTitle; - private CharSequence itemTitleCondensed; - private int itemIconResId; - private char itemAlphabeticShortcut; - private char itemNumericShortcut; - /** - * Sync to attrs.xml enum: - * - 0: none - * - 1: all - * - 2: exclusive - */ - private int itemCheckable; - private boolean itemChecked; - private boolean itemVisible; - private boolean itemEnabled; - - /** - * Sync to attrs.xml enum, values in MenuItem: - * - 0: never - * - 1: ifRoom - * - 2: always - * - -1: Safe sentinel for "no value". - */ - private int itemShowAsAction; - - private int itemActionViewLayout; - private String itemActionViewClassName; - private String itemActionProviderClassName; - - private String itemListenerMethodName; - - private ActionProvider itemActionProvider; - - private static final int defaultGroupId = NO_ID; - private static final int defaultItemId = NO_ID; - private static final int defaultItemCategory = 0; - private static final int defaultItemOrder = 0; - private static final int defaultItemCheckable = 0; - private static final boolean defaultItemChecked = false; - private static final boolean defaultItemVisible = true; - private static final boolean defaultItemEnabled = true; - - public MenuState(final Menu menu) { - this.menu = menu; - - resetGroup(); - } - - public void resetGroup() { - groupId = defaultGroupId; - groupCategory = defaultItemCategory; - groupOrder = defaultItemOrder; - groupCheckable = defaultItemCheckable; - groupVisible = defaultItemVisible; - groupEnabled = defaultItemEnabled; - } - - /** - * Called when the parser is pointing to a group tag. - */ - public void readGroup(AttributeSet attrs) { - TypedArray a = mContext.obtainStyledAttributes(attrs, - R.styleable.SherlockMenuGroup); - - groupId = a.getResourceId(R.styleable.SherlockMenuGroup_android_id, defaultGroupId); - groupCategory = a.getInt(R.styleable.SherlockMenuGroup_android_menuCategory, defaultItemCategory); - groupOrder = a.getInt(R.styleable.SherlockMenuGroup_android_orderInCategory, defaultItemOrder); - groupCheckable = a.getInt(R.styleable.SherlockMenuGroup_android_checkableBehavior, defaultItemCheckable); - groupVisible = a.getBoolean(R.styleable.SherlockMenuGroup_android_visible, defaultItemVisible); - groupEnabled = a.getBoolean(R.styleable.SherlockMenuGroup_android_enabled, defaultItemEnabled); - - a.recycle(); - } - - /** - * Called when the parser is pointing to an item tag. - */ - public void readItem(AttributeSet attrs) { - TypedArray a = mContext.obtainStyledAttributes(attrs, - R.styleable.SherlockMenuItem); - - // Inherit attributes from the group as default value - itemId = a.getResourceId(R.styleable.SherlockMenuItem_android_id, defaultItemId); - final int category = a.getInt(R.styleable.SherlockMenuItem_android_menuCategory, groupCategory); - final int order = a.getInt(R.styleable.SherlockMenuItem_android_orderInCategory, groupOrder); - itemCategoryOrder = (category & Menu.CATEGORY_MASK) | (order & Menu.USER_MASK); - itemTitle = a.getText(R.styleable.SherlockMenuItem_android_title); - itemTitleCondensed = a.getText(R.styleable.SherlockMenuItem_android_titleCondensed); - itemIconResId = a.getResourceId(R.styleable.SherlockMenuItem_android_icon, 0); - itemAlphabeticShortcut = - getShortcut(a.getString(R.styleable.SherlockMenuItem_android_alphabeticShortcut)); - itemNumericShortcut = - getShortcut(a.getString(R.styleable.SherlockMenuItem_android_numericShortcut)); - if (a.hasValue(R.styleable.SherlockMenuItem_android_checkable)) { - // Item has attribute checkable, use it - itemCheckable = a.getBoolean(R.styleable.SherlockMenuItem_android_checkable, false) ? 1 : 0; - } else { - // Item does not have attribute, use the group's (group can have one more state - // for checkable that represents the exclusive checkable) - itemCheckable = groupCheckable; - } - - itemChecked = a.getBoolean(R.styleable.SherlockMenuItem_android_checked, defaultItemChecked); - itemVisible = a.getBoolean(R.styleable.SherlockMenuItem_android_visible, groupVisible); - itemEnabled = a.getBoolean(R.styleable.SherlockMenuItem_android_enabled, groupEnabled); - - TypedValue value = new TypedValue(); - a.getValue(R.styleable.SherlockMenuItem_android_showAsAction, value); - itemShowAsAction = value.type == TypedValue.TYPE_INT_HEX ? value.data : -1; - - itemListenerMethodName = a.getString(R.styleable.SherlockMenuItem_android_onClick); - itemActionViewLayout = a.getResourceId(R.styleable.SherlockMenuItem_android_actionLayout, 0); - - // itemActionViewClassName = a.getString(R.styleable.SherlockMenuItem_android_actionViewClass); - value = new TypedValue(); - a.getValue(R.styleable.SherlockMenuItem_android_actionViewClass, value); - itemActionViewClassName = value.type == TypedValue.TYPE_STRING ? value.string.toString() : null; - - // itemActionProviderClassName = a.getString(R.styleable.SherlockMenuItem_android_actionProviderClass); - value = new TypedValue(); - a.getValue(R.styleable.SherlockMenuItem_android_actionProviderClass, value); - itemActionProviderClassName = value.type == TypedValue.TYPE_STRING ? value.string.toString() : null; - - final boolean hasActionProvider = itemActionProviderClassName != null; - if (hasActionProvider && itemActionViewLayout == 0 && itemActionViewClassName == null) { - itemActionProvider = newInstance(itemActionProviderClassName, - ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE, - mActionProviderConstructorArguments); - } else { - if (hasActionProvider) { - Log.w(LOG_TAG, "Ignoring attribute 'actionProviderClass'." - + " Action view already specified."); - } - itemActionProvider = null; - } - - a.recycle(); - - itemAdded = false; - } - - private char getShortcut(String shortcutString) { - if (shortcutString == null) { - return 0; - } else { - return shortcutString.charAt(0); - } - } - - private void setItem(MenuItem item) { - item.setChecked(itemChecked) - .setVisible(itemVisible) - .setEnabled(itemEnabled) - .setCheckable(itemCheckable >= 1) - .setTitleCondensed(itemTitleCondensed) - .setIcon(itemIconResId) - .setAlphabeticShortcut(itemAlphabeticShortcut) - .setNumericShortcut(itemNumericShortcut); - - if (itemShowAsAction >= 0) { - item.setShowAsAction(itemShowAsAction); - } - - if (itemListenerMethodName != null) { - if (mContext.isRestricted()) { - throw new IllegalStateException("The android:onClick attribute cannot " - + "be used within a restricted context"); - } - item.setOnMenuItemClickListener( - new InflatedOnMenuItemClickListener(mRealOwner, itemListenerMethodName)); - } - - if (itemCheckable >= 2) { - if (item instanceof MenuItemImpl) { - MenuItemImpl impl = (MenuItemImpl) item; - impl.setExclusiveCheckable(true); - } else { - menu.setGroupCheckable(groupId, true, true); - } - } - - boolean actionViewSpecified = false; - if (itemActionViewClassName != null) { - View actionView = (View) newInstance(itemActionViewClassName, - ACTION_VIEW_CONSTRUCTOR_SIGNATURE, mActionViewConstructorArguments); - item.setActionView(actionView); - actionViewSpecified = true; - } - if (itemActionViewLayout > 0) { - if (!actionViewSpecified) { - item.setActionView(itemActionViewLayout); - actionViewSpecified = true; - } else { - Log.w(LOG_TAG, "Ignoring attribute 'itemActionViewLayout'." - + " Action view already specified."); - } - } - if (itemActionProvider != null) { - item.setActionProvider(itemActionProvider); - } - } - - public void addItem() { - itemAdded = true; - setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle)); - } - - public SubMenu addSubMenuItem() { - itemAdded = true; - SubMenu subMenu = menu.addSubMenu(groupId, itemId, itemCategoryOrder, itemTitle); - setItem(subMenu.getItem()); - return subMenu; - } - - public boolean hasAddedItem() { - return itemAdded; - } - - @SuppressWarnings("unchecked") - private T newInstance(String className, Class[] constructorSignature, - Object[] arguments) { - try { - Class clazz = mContext.getClassLoader().loadClass(className); - Constructor constructor = clazz.getConstructor(constructorSignature); - return (T) constructor.newInstance(arguments); - } catch (Exception e) { - Log.w(LOG_TAG, "Cannot instantiate class: " + className, e); - } - return null; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java deleted file mode 100644 index 7fc3aa430..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java +++ /dev/null @@ -1,598 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import android.content.Intent; -import android.graphics.drawable.Drawable; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.View; - -/** - * Interface for direct access to a previously created menu item. - *

- * An Item is returned by calling one of the {@link android.view.Menu#add} - * methods. - *

- * For a feature set of specific menu types, see {@link Menu}. - * - *

- *

Developer Guides

- *

For information about creating menus, read the - * Menus developer guide.

- *
- */ -public interface MenuItem { - /* - * These should be kept in sync with attrs.xml enum constants for showAsAction - */ - /** Never show this item as a button in an Action Bar. */ - public static final int SHOW_AS_ACTION_NEVER = android.view.MenuItem.SHOW_AS_ACTION_NEVER; - /** Show this item as a button in an Action Bar if the system decides there is room for it. */ - public static final int SHOW_AS_ACTION_IF_ROOM = android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM; - /** - * Always show this item as a button in an Action Bar. - * Use sparingly! If too many items are set to always show in the Action Bar it can - * crowd the Action Bar and degrade the user experience on devices with smaller screens. - * A good rule of thumb is to have no more than 2 items set to always show at a time. - */ - public static final int SHOW_AS_ACTION_ALWAYS = android.view.MenuItem.SHOW_AS_ACTION_ALWAYS; - - /** - * When this item is in the action bar, always show it with a text label even if - * it also has an icon specified. - */ - public static final int SHOW_AS_ACTION_WITH_TEXT = android.view.MenuItem.SHOW_AS_ACTION_WITH_TEXT; - - /** - * This item's action view collapses to a normal menu item. - * When expanded, the action view temporarily takes over - * a larger segment of its container. - */ - public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = android.view.MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW; - - /** - * Interface definition for a callback to be invoked when a menu item is - * clicked. - * - * @see Activity#onContextItemSelected(MenuItem) - * @see Activity#onOptionsItemSelected(MenuItem) - */ - public interface OnMenuItemClickListener { - /** - * Called when a menu item has been invoked. This is the first code - * that is executed; if it returns true, no other callbacks will be - * executed. - * - * @param item The menu item that was invoked. - * - * @return Return true to consume this click and prevent others from - * executing. - */ - public boolean onMenuItemClick(MenuItem item); - } - - /** - * Interface definition for a callback to be invoked when a menu item - * marked with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} is - * expanded or collapsed. - * - * @see MenuItem#expandActionView() - * @see MenuItem#collapseActionView() - * @see MenuItem#setShowAsActionFlags(int) - */ - public interface OnActionExpandListener { - /** - * Called when a menu item with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} - * is expanded. - * @param item Item that was expanded - * @return true if the item should expand, false if expansion should be suppressed. - */ - public boolean onMenuItemActionExpand(MenuItem item); - - /** - * Called when a menu item with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} - * is collapsed. - * @param item Item that was collapsed - * @return true if the item should collapse, false if collapsing should be suppressed. - */ - public boolean onMenuItemActionCollapse(MenuItem item); - } - - /** - * Return the identifier for this menu item. The identifier can not - * be changed after the menu is created. - * - * @return The menu item's identifier. - */ - public int getItemId(); - - /** - * Return the group identifier that this menu item is part of. The group - * identifier can not be changed after the menu is created. - * - * @return The menu item's group identifier. - */ - public int getGroupId(); - - /** - * Return the category and order within the category of this item. This - * item will be shown before all items (within its category) that have - * order greater than this value. - *

- * An order integer contains the item's category (the upper bits of the - * integer; set by or/add the category with the order within the - * category) and the ordering of the item within that category (the - * lower bits). Example categories are {@link Menu#CATEGORY_SYSTEM}, - * {@link Menu#CATEGORY_SECONDARY}, {@link Menu#CATEGORY_ALTERNATIVE}, - * {@link Menu#CATEGORY_CONTAINER}. See {@link Menu} for a full list. - * - * @return The order of this item. - */ - public int getOrder(); - - /** - * Change the title associated with this item. - * - * @param title The new text to be displayed. - * @return This Item so additional setters can be called. - */ - public MenuItem setTitle(CharSequence title); - - /** - * Change the title associated with this item. - *

- * Some menu types do not sufficient space to show the full title, and - * instead a condensed title is preferred. See {@link Menu} for more - * information. - * - * @param title The resource id of the new text to be displayed. - * @return This Item so additional setters can be called. - * @see #setTitleCondensed(CharSequence) - */ - - public MenuItem setTitle(int title); - - /** - * Retrieve the current title of the item. - * - * @return The title. - */ - public CharSequence getTitle(); - - /** - * Change the condensed title associated with this item. The condensed - * title is used in situations where the normal title may be too long to - * be displayed. - * - * @param title The new text to be displayed as the condensed title. - * @return This Item so additional setters can be called. - */ - public MenuItem setTitleCondensed(CharSequence title); - - /** - * Retrieve the current condensed title of the item. If a condensed - * title was never set, it will return the normal title. - * - * @return The condensed title, if it exists. - * Otherwise the normal title. - */ - public CharSequence getTitleCondensed(); - - /** - * Change the icon associated with this item. This icon will not always be - * shown, so the title should be sufficient in describing this item. See - * {@link Menu} for the menu types that support icons. - * - * @param icon The new icon (as a Drawable) to be displayed. - * @return This Item so additional setters can be called. - */ - public MenuItem setIcon(Drawable icon); - - /** - * Change the icon associated with this item. This icon will not always be - * shown, so the title should be sufficient in describing this item. See - * {@link Menu} for the menu types that support icons. - *

- * This method will set the resource ID of the icon which will be used to - * lazily get the Drawable when this item is being shown. - * - * @param iconRes The new icon (as a resource ID) to be displayed. - * @return This Item so additional setters can be called. - */ - public MenuItem setIcon(int iconRes); - - /** - * Returns the icon for this item as a Drawable (getting it from resources if it hasn't been - * loaded before). - * - * @return The icon as a Drawable. - */ - public Drawable getIcon(); - - /** - * Change the Intent associated with this item. By default there is no - * Intent associated with a menu item. If you set one, and nothing - * else handles the item, then the default behavior will be to call - * {@link android.content.Context#startActivity} with the given Intent. - * - *

Note that setIntent() can not be used with the versions of - * {@link Menu#add} that take a Runnable, because {@link Runnable#run} - * does not return a value so there is no way to tell if it handled the - * item. In this case it is assumed that the Runnable always handles - * the item, and the intent will never be started. - * - * @see #getIntent - * @param intent The Intent to associated with the item. This Intent - * object is not copied, so be careful not to - * modify it later. - * @return This Item so additional setters can be called. - */ - public MenuItem setIntent(Intent intent); - - /** - * Return the Intent associated with this item. This returns a - * reference to the Intent which you can change as desired to modify - * what the Item is holding. - * - * @see #setIntent - * @return Returns the last value supplied to {@link #setIntent}, or - * null. - */ - public Intent getIntent(); - - /** - * Change both the numeric and alphabetic shortcut associated with this - * item. Note that the shortcut will be triggered when the key that - * generates the given character is pressed alone or along with with the alt - * key. Also note that case is not significant and that alphabetic shortcut - * characters will be displayed in lower case. - *

- * See {@link Menu} for the menu types that support shortcuts. - * - * @param numericChar The numeric shortcut key. This is the shortcut when - * using a numeric (e.g., 12-key) keyboard. - * @param alphaChar The alphabetic shortcut key. This is the shortcut when - * using a keyboard with alphabetic keys. - * @return This Item so additional setters can be called. - */ - public MenuItem setShortcut(char numericChar, char alphaChar); - - /** - * Change the numeric shortcut associated with this item. - *

- * See {@link Menu} for the menu types that support shortcuts. - * - * @param numericChar The numeric shortcut key. This is the shortcut when - * using a 12-key (numeric) keyboard. - * @return This Item so additional setters can be called. - */ - public MenuItem setNumericShortcut(char numericChar); - - /** - * Return the char for this menu item's numeric (12-key) shortcut. - * - * @return Numeric character to use as a shortcut. - */ - public char getNumericShortcut(); - - /** - * Change the alphabetic shortcut associated with this item. The shortcut - * will be triggered when the key that generates the given character is - * pressed alone or along with with the alt key. Case is not significant and - * shortcut characters will be displayed in lower case. Note that menu items - * with the characters '\b' or '\n' as shortcuts will get triggered by the - * Delete key or Carriage Return key, respectively. - *

- * See {@link Menu} for the menu types that support shortcuts. - * - * @param alphaChar The alphabetic shortcut key. This is the shortcut when - * using a keyboard with alphabetic keys. - * @return This Item so additional setters can be called. - */ - public MenuItem setAlphabeticShortcut(char alphaChar); - - /** - * Return the char for this menu item's alphabetic shortcut. - * - * @return Alphabetic character to use as a shortcut. - */ - public char getAlphabeticShortcut(); - - /** - * Control whether this item can display a check mark. Setting this does - * not actually display a check mark (see {@link #setChecked} for that); - * rather, it ensures there is room in the item in which to display a - * check mark. - *

- * See {@link Menu} for the menu types that support check marks. - * - * @param checkable Set to true to allow a check mark, false to - * disallow. The default is false. - * @see #setChecked - * @see #isCheckable - * @see Menu#setGroupCheckable - * @return This Item so additional setters can be called. - */ - public MenuItem setCheckable(boolean checkable); - - /** - * Return whether the item can currently display a check mark. - * - * @return If a check mark can be displayed, returns true. - * - * @see #setCheckable - */ - public boolean isCheckable(); - - /** - * Control whether this item is shown with a check mark. Note that you - * must first have enabled checking with {@link #setCheckable} or else - * the check mark will not appear. If this item is a member of a group that contains - * mutually-exclusive items (set via {@link Menu#setGroupCheckable(int, boolean, boolean)}, - * the other items in the group will be unchecked. - *

- * See {@link Menu} for the menu types that support check marks. - * - * @see #setCheckable - * @see #isChecked - * @see Menu#setGroupCheckable - * @param checked Set to true to display a check mark, false to hide - * it. The default value is false. - * @return This Item so additional setters can be called. - */ - public MenuItem setChecked(boolean checked); - - /** - * Return whether the item is currently displaying a check mark. - * - * @return If a check mark is displayed, returns true. - * - * @see #setChecked - */ - public boolean isChecked(); - - /** - * Sets the visibility of the menu item. Even if a menu item is not visible, - * it may still be invoked via its shortcut (to completely disable an item, - * set it to invisible and {@link #setEnabled(boolean) disabled}). - * - * @param visible If true then the item will be visible; if false it is - * hidden. - * @return This Item so additional setters can be called. - */ - public MenuItem setVisible(boolean visible); - - /** - * Return the visibility of the menu item. - * - * @return If true the item is visible; else it is hidden. - */ - public boolean isVisible(); - - /** - * Sets whether the menu item is enabled. Disabling a menu item will not - * allow it to be invoked via its shortcut. The menu item will still be - * visible. - * - * @param enabled If true then the item will be invokable; if false it is - * won't be invokable. - * @return This Item so additional setters can be called. - */ - public MenuItem setEnabled(boolean enabled); - - /** - * Return the enabled state of the menu item. - * - * @return If true the item is enabled and hence invokable; else it is not. - */ - public boolean isEnabled(); - - /** - * Check whether this item has an associated sub-menu. I.e. it is a - * sub-menu of another menu. - * - * @return If true this item has a menu; else it is a - * normal item. - */ - public boolean hasSubMenu(); - - /** - * Get the sub-menu to be invoked when this item is selected, if it has - * one. See {@link #hasSubMenu()}. - * - * @return The associated menu if there is one, else null - */ - public SubMenu getSubMenu(); - - /** - * Set a custom listener for invocation of this menu item. In most - * situations, it is more efficient and easier to use - * {@link Activity#onOptionsItemSelected(MenuItem)} or - * {@link Activity#onContextItemSelected(MenuItem)}. - * - * @param menuItemClickListener The object to receive invokations. - * @return This Item so additional setters can be called. - * @see Activity#onOptionsItemSelected(MenuItem) - * @see Activity#onContextItemSelected(MenuItem) - */ - public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener menuItemClickListener); - - /** - * Gets the extra information linked to this menu item. This extra - * information is set by the View that added this menu item to the - * menu. - * - * @see OnCreateContextMenuListener - * @return The extra information linked to the View that added this - * menu item to the menu. This can be null. - */ - public ContextMenuInfo getMenuInfo(); - - /** - * Sets how this item should display in the presence of an Action Bar. - * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS}, - * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should - * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}. - * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action, - * it should be shown with a text label. - * - * @param actionEnum How the item should display. One of - * {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or - * {@link #SHOW_AS_ACTION_NEVER}. SHOW_AS_ACTION_NEVER is the default. - * - * @see android.app.ActionBar - * @see #setActionView(View) - */ - public void setShowAsAction(int actionEnum); - - /** - * Sets how this item should display in the presence of an Action Bar. - * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS}, - * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should - * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}. - * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action, - * it should be shown with a text label. - * - *

Note: This method differs from {@link #setShowAsAction(int)} only in that it - * returns the current MenuItem instance for call chaining. - * - * @param actionEnum How the item should display. One of - * {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or - * {@link #SHOW_AS_ACTION_NEVER}. SHOW_AS_ACTION_NEVER is the default. - * - * @see android.app.ActionBar - * @see #setActionView(View) - * @return This MenuItem instance for call chaining. - */ - public MenuItem setShowAsActionFlags(int actionEnum); - - /** - * Set an action view for this menu item. An action view will be displayed in place - * of an automatically generated menu item element in the UI when this item is shown - * as an action within a parent. - *

- * Note: Setting an action view overrides the action provider - * set via {@link #setActionProvider(ActionProvider)}. - *

- * - * @param view View to use for presenting this item to the user. - * @return This Item so additional setters can be called. - * - * @see #setShowAsAction(int) - */ - public MenuItem setActionView(View view); - - /** - * Set an action view for this menu item. An action view will be displayed in place - * of an automatically generated menu item element in the UI when this item is shown - * as an action within a parent. - *

- * Note: Setting an action view overrides the action provider - * set via {@link #setActionProvider(ActionProvider)}. - *

- * - * @param resId Layout resource to use for presenting this item to the user. - * @return This Item so additional setters can be called. - * - * @see #setShowAsAction(int) - */ - public MenuItem setActionView(int resId); - - /** - * Returns the currently set action view for this menu item. - * - * @return This item's action view - * - * @see #setActionView(View) - * @see #setShowAsAction(int) - */ - public View getActionView(); - - /** - * Sets the {@link ActionProvider} responsible for creating an action view if - * the item is placed on the action bar. The provider also provides a default - * action invoked if the item is placed in the overflow menu. - *

- * Note: Setting an action provider overrides the action view - * set via {@link #setActionView(int)} or {@link #setActionView(View)}. - *

- * - * @param actionProvider The action provider. - * @return This Item so additional setters can be called. - * - * @see ActionProvider - */ - public MenuItem setActionProvider(ActionProvider actionProvider); - - /** - * Gets the {@link ActionProvider}. - * - * @return The action provider. - * - * @see ActionProvider - * @see #setActionProvider(ActionProvider) - */ - public ActionProvider getActionProvider(); - - /** - * Expand the action view associated with this menu item. - * The menu item must have an action view set, as well as - * the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. - * If a listener has been set using {@link #setOnActionExpandListener(OnActionExpandListener)} - * it will have its {@link OnActionExpandListener#onMenuItemActionExpand(MenuItem)} - * method invoked. The listener may return false from this method to prevent expanding - * the action view. - * - * @return true if the action view was expanded, false otherwise. - */ - public boolean expandActionView(); - - /** - * Collapse the action view associated with this menu item. - * The menu item must have an action view set, as well as the showAsAction flag - * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. If a listener has been set using - * {@link #setOnActionExpandListener(OnActionExpandListener)} it will have its - * {@link OnActionExpandListener#onMenuItemActionCollapse(MenuItem)} method invoked. - * The listener may return false from this method to prevent collapsing the action view. - * - * @return true if the action view was collapsed, false otherwise. - */ - public boolean collapseActionView(); - - /** - * Returns true if this menu item's action view has been expanded. - * - * @return true if the item's action view is expanded, false otherwise. - * - * @see #expandActionView() - * @see #collapseActionView() - * @see #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW - * @see OnActionExpandListener - */ - public boolean isActionViewExpanded(); - - /** - * Set an {@link OnActionExpandListener} on this menu item to be notified when - * the associated action view is expanded or collapsed. The menu item must - * be configured to expand or collapse its action view using the flag - * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. - * - * @param listener Listener that will respond to expand/collapse events - * @return This menu item instance for call chaining - */ - public MenuItem setOnActionExpandListener(OnActionExpandListener listener); -} \ No newline at end of file diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java deleted file mode 100644 index 397fd1c2d..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import android.graphics.drawable.Drawable; -import android.view.View; - -/** - * Subclass of {@link Menu} for sub menus. - *

- * Sub menus do not support item icons, or nested sub menus. - * - *

- *

Developer Guides

- *

For information about creating menus, read the - * Menus developer guide.

- *
- */ - -public interface SubMenu extends Menu { - /** - * Sets the submenu header's title to the title given in titleRes - * resource identifier. - * - * @param titleRes The string resource identifier used for the title. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderTitle(int titleRes); - - /** - * Sets the submenu header's title to the title given in title. - * - * @param title The character sequence used for the title. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderTitle(CharSequence title); - - /** - * Sets the submenu header's icon to the icon given in iconRes - * resource id. - * - * @param iconRes The resource identifier used for the icon. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderIcon(int iconRes); - - /** - * Sets the submenu header's icon to the icon given in icon - * {@link Drawable}. - * - * @param icon The {@link Drawable} used for the icon. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderIcon(Drawable icon); - - /** - * Sets the header of the submenu to the {@link View} given in - * view. This replaces the header title and icon (and those - * replace this). - * - * @param view The {@link View} used for the header. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setHeaderView(View view); - - /** - * Clears the header of the submenu. - */ - public void clearHeader(); - - /** - * Change the icon associated with this submenu's item in its parent menu. - * - * @see MenuItem#setIcon(int) - * @param iconRes The new icon (as a resource ID) to be displayed. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setIcon(int iconRes); - - /** - * Change the icon associated with this submenu's item in its parent menu. - * - * @see MenuItem#setIcon(Drawable) - * @param icon The new icon (as a Drawable) to be displayed. - * @return This SubMenu so additional setters can be called. - */ - public SubMenu setIcon(Drawable icon); - - /** - * Gets the {@link MenuItem} that represents this submenu in the parent - * menu. Use this for setting additional item attributes. - * - * @return The {@link MenuItem} that launches the submenu when invoked. - */ - public MenuItem getItem(); -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java deleted file mode 100644 index a340a4291..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * Copyright (C) 2011 Jake Wharton - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.view; - -import android.content.Context; - -/** - *

Abstract base class for a top-level window look and behavior policy. An - * instance of this class should be used as the top-level view added to the - * window manager. It provides standard UI policies such as a background, title - * area, default key processing, etc.

- * - *

The only existing implementation of this abstract class is - * android.policy.PhoneWindow, which you should instantiate when needing a - * Window. Eventually that class will be refactored and a factory method added - * for creating Window instances without knowing about a particular - * implementation.

- */ -public abstract class Window extends android.view.Window { - public static final long FEATURE_ACTION_BAR = android.view.Window.FEATURE_ACTION_BAR; - public static final long FEATURE_ACTION_BAR_OVERLAY = android.view.Window.FEATURE_ACTION_BAR_OVERLAY; - public static final long FEATURE_ACTION_MODE_OVERLAY = android.view.Window.FEATURE_ACTION_MODE_OVERLAY; - public static final long FEATURE_NO_TITLE = android.view.Window.FEATURE_NO_TITLE; - public static final long FEATURE_PROGRESS = android.view.Window.FEATURE_PROGRESS; - public static final long FEATURE_INDETERMINATE_PROGRESS = android.view.Window.FEATURE_INDETERMINATE_PROGRESS; - - /** - * Create a new instance for a context. - * - * @param context Context. - */ - private Window(Context context) { - super(context); - } - - - public interface Callback { - /** - * Called when a panel's menu item has been selected by the user. - * - * @param featureId The panel that the menu is in. - * @param item The menu item that was selected. - * - * @return boolean Return true to finish processing of selection, or - * false to perform the normal menu handling (calling its - * Runnable or sending a Message to its target Handler). - */ - public boolean onMenuItemSelected(int featureId, MenuItem item); - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java deleted file mode 100644 index d7f110fc6..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java +++ /dev/null @@ -1,1104 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.widget; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ResolveInfo; -import android.database.DataSetObservable; -import android.os.Handler; -import android.text.TextUtils; -import android.util.Log; -import android.util.Xml; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -/** - *

- * This class represents a data model for choosing a component for handing a - * given {@link Intent}. The model is responsible for querying the system for - * activities that can handle the given intent and order found activities - * based on historical data of previous choices. The historical data is stored - * in an application private file. If a client does not want to have persistent - * choice history the file can be omitted, thus the activities will be ordered - * based on historical usage for the current session. - *

- *

- * For each backing history file there is a singleton instance of this class. Thus, - * several clients that specify the same history file will share the same model. Note - * that if multiple clients are sharing the same model they should implement semantically - * equivalent functionality since setting the model intent will change the found - * activities and they may be inconsistent with the functionality of some of the clients. - * For example, choosing a share activity can be implemented by a single backing - * model and two different views for performing the selection. If however, one of the - * views is used for sharing but the other for importing, for example, then each - * view should be backed by a separate model. - *

- *

- * The way clients interact with this class is as follows: - *

- *

- *

- * 
- *  // Get a model and set it to a couple of clients with semantically similar function.
- *  ActivityChooserModel dataModel =
- *      ActivityChooserModel.get(context, "task_specific_history_file_name.xml");
- *
- *  ActivityChooserModelClient modelClient1 = getActivityChooserModelClient1();
- *  modelClient1.setActivityChooserModel(dataModel);
- *
- *  ActivityChooserModelClient modelClient2 = getActivityChooserModelClient2();
- *  modelClient2.setActivityChooserModel(dataModel);
- *
- *  // Set an intent to choose a an activity for.
- *  dataModel.setIntent(intent);
- * 
- * 
- * 

- *

- * Note: This class is thread safe. - *

- * - * @hide - */ -class ActivityChooserModel extends DataSetObservable { - - /** - * Client that utilizes an {@link ActivityChooserModel}. - */ - public interface ActivityChooserModelClient { - - /** - * Sets the {@link ActivityChooserModel}. - * - * @param dataModel The model. - */ - public void setActivityChooserModel(ActivityChooserModel dataModel); - } - - /** - * Defines a sorter that is responsible for sorting the activities - * based on the provided historical choices and an intent. - */ - public interface ActivitySorter { - - /** - * Sorts the activities in descending order of relevance - * based on previous history and an intent. - * - * @param intent The {@link Intent}. - * @param activities Activities to be sorted. - * @param historicalRecords Historical records. - */ - // This cannot be done by a simple comparator since an Activity weight - // is computed from history. Note that Activity implements Comparable. - public void sort(Intent intent, List activities, - List historicalRecords); - } - - /** - * Listener for choosing an activity. - */ - public interface OnChooseActivityListener { - - /** - * Called when an activity has been chosen. The client can decide whether - * an activity can be chosen and if so the caller of - * {@link ActivityChooserModel#chooseActivity(int)} will receive and {@link Intent} - * for launching it. - *

- * Note: Modifying the intent is not permitted and - * any changes to the latter will be ignored. - *

- * - * @param host The listener's host model. - * @param intent The intent for launching the chosen activity. - * @return Whether the intent is handled and should not be delivered to clients. - * - * @see ActivityChooserModel#chooseActivity(int) - */ - public boolean onChooseActivity(ActivityChooserModel host, Intent intent); - } - - /** - * Flag for selecting debug mode. - */ - private static final boolean DEBUG = false; - - /** - * Tag used for logging. - */ - private static final String LOG_TAG = ActivityChooserModel.class.getSimpleName(); - - /** - * The root tag in the history file. - */ - private static final String TAG_HISTORICAL_RECORDS = "historical-records"; - - /** - * The tag for a record in the history file. - */ - private static final String TAG_HISTORICAL_RECORD = "historical-record"; - - /** - * Attribute for the activity. - */ - private static final String ATTRIBUTE_ACTIVITY = "activity"; - - /** - * Attribute for the choice time. - */ - private static final String ATTRIBUTE_TIME = "time"; - - /** - * Attribute for the choice weight. - */ - private static final String ATTRIBUTE_WEIGHT = "weight"; - - /** - * The default name of the choice history file. - */ - public static final String DEFAULT_HISTORY_FILE_NAME = - "activity_choser_model_history.xml"; - - /** - * The default maximal length of the choice history. - */ - public static final int DEFAULT_HISTORY_MAX_LENGTH = 50; - - /** - * The amount with which to inflate a chosen activity when set as default. - */ - private static final int DEFAULT_ACTIVITY_INFLATION = 5; - - /** - * Default weight for a choice record. - */ - private static final float DEFAULT_HISTORICAL_RECORD_WEIGHT = 1.0f; - - /** - * The extension of the history file. - */ - private static final String HISTORY_FILE_EXTENSION = ".xml"; - - /** - * An invalid item index. - */ - private static final int INVALID_INDEX = -1; - - /** - * Lock to guard the model registry. - */ - private static final Object sRegistryLock = new Object(); - - /** - * This the registry for data models. - */ - private static final Map sDataModelRegistry = - new HashMap(); - - /** - * Lock for synchronizing on this instance. - */ - private final Object mInstanceLock = new Object(); - - /** - * List of activities that can handle the current intent. - */ - private final List mActivites = new ArrayList(); - - /** - * List with historical choice records. - */ - private final List mHistoricalRecords = new ArrayList(); - - /** - * Context for accessing resources. - */ - private final Context mContext; - - /** - * The name of the history file that backs this model. - */ - private final String mHistoryFileName; - - /** - * The intent for which a activity is being chosen. - */ - private Intent mIntent; - - /** - * The sorter for ordering activities based on intent and past choices. - */ - private ActivitySorter mActivitySorter = new DefaultSorter(); - - /** - * The maximal length of the choice history. - */ - private int mHistoryMaxSize = DEFAULT_HISTORY_MAX_LENGTH; - - /** - * Flag whether choice history can be read. In general many clients can - * share the same data model and {@link #readHistoricalData()} may be called - * by arbitrary of them any number of times. Therefore, this class guarantees - * that the very first read succeeds and subsequent reads can be performed - * only after a call to {@link #persistHistoricalData()} followed by change - * of the share records. - */ - private boolean mCanReadHistoricalData = true; - - /** - * Flag whether the choice history was read. This is used to enforce that - * before calling {@link #persistHistoricalData()} a call to - * {@link #persistHistoricalData()} has been made. This aims to avoid a - * scenario in which a choice history file exits, it is not read yet and - * it is overwritten. Note that always all historical records are read in - * full and the file is rewritten. This is necessary since we need to - * purge old records that are outside of the sliding window of past choices. - */ - private boolean mReadShareHistoryCalled = false; - - /** - * Flag whether the choice records have changed. In general many clients can - * share the same data model and {@link #persistHistoricalData()} may be called - * by arbitrary of them any number of times. Therefore, this class guarantees - * that choice history will be persisted only if it has changed. - */ - private boolean mHistoricalRecordsChanged = true; - - /** - * Hander for scheduling work on client tread. - */ - private final Handler mHandler = new Handler(); - - /** - * Policy for controlling how the model handles chosen activities. - */ - private OnChooseActivityListener mActivityChoserModelPolicy; - - /** - * Gets the data model backed by the contents of the provided file with historical data. - * Note that only one data model is backed by a given file, thus multiple calls with - * the same file name will return the same model instance. If no such instance is present - * it is created. - *

- * Note: To use the default historical data file clients should explicitly - * pass as file name {@link #DEFAULT_HISTORY_FILE_NAME}. If no persistence of the choice - * history is desired clients should pass null for the file name. In such - * case a new model is returned for each invocation. - *

- * - *

- * Always use difference historical data files for semantically different actions. - * For example, sharing is different from importing. - *

- * - * @param context Context for loading resources. - * @param historyFileName File name with choice history, null - * if the model should not be backed by a file. In this case the activities - * will be ordered only by data from the current session. - * - * @return The model. - */ - public static ActivityChooserModel get(Context context, String historyFileName) { - synchronized (sRegistryLock) { - ActivityChooserModel dataModel = sDataModelRegistry.get(historyFileName); - if (dataModel == null) { - dataModel = new ActivityChooserModel(context, historyFileName); - sDataModelRegistry.put(historyFileName, dataModel); - } - dataModel.readHistoricalData(); - return dataModel; - } - } - - /** - * Creates a new instance. - * - * @param context Context for loading resources. - * @param historyFileName The history XML file. - */ - private ActivityChooserModel(Context context, String historyFileName) { - mContext = context.getApplicationContext(); - if (!TextUtils.isEmpty(historyFileName) - && !historyFileName.endsWith(HISTORY_FILE_EXTENSION)) { - mHistoryFileName = historyFileName + HISTORY_FILE_EXTENSION; - } else { - mHistoryFileName = historyFileName; - } - } - - /** - * Sets an intent for which to choose a activity. - *

- * Note: Clients must set only semantically similar - * intents for each data model. - *

- * - * @param intent The intent. - */ - public void setIntent(Intent intent) { - synchronized (mInstanceLock) { - if (mIntent == intent) { - return; - } - mIntent = intent; - loadActivitiesLocked(); - } - } - - /** - * Gets the intent for which a activity is being chosen. - * - * @return The intent. - */ - public Intent getIntent() { - synchronized (mInstanceLock) { - return mIntent; - } - } - - /** - * Gets the number of activities that can handle the intent. - * - * @return The activity count. - * - * @see #setIntent(Intent) - */ - public int getActivityCount() { - synchronized (mInstanceLock) { - return mActivites.size(); - } - } - - /** - * Gets an activity at a given index. - * - * @return The activity. - * - * @see ActivityResolveInfo - * @see #setIntent(Intent) - */ - public ResolveInfo getActivity(int index) { - synchronized (mInstanceLock) { - return mActivites.get(index).resolveInfo; - } - } - - /** - * Gets the index of a the given activity. - * - * @param activity The activity index. - * - * @return The index if found, -1 otherwise. - */ - public int getActivityIndex(ResolveInfo activity) { - List activities = mActivites; - final int activityCount = activities.size(); - for (int i = 0; i < activityCount; i++) { - ActivityResolveInfo currentActivity = activities.get(i); - if (currentActivity.resolveInfo == activity) { - return i; - } - } - return INVALID_INDEX; - } - - /** - * Chooses a activity to handle the current intent. This will result in - * adding a historical record for that action and construct intent with - * its component name set such that it can be immediately started by the - * client. - *

- * Note: By calling this method the client guarantees - * that the returned intent will be started. This intent is returned to - * the client solely to let additional customization before the start. - *

- * - * @return An {@link Intent} for launching the activity or null if the - * policy has consumed the intent. - * - * @see HistoricalRecord - * @see OnChooseActivityListener - */ - public Intent chooseActivity(int index) { - ActivityResolveInfo chosenActivity = mActivites.get(index); - - ComponentName chosenName = new ComponentName( - chosenActivity.resolveInfo.activityInfo.packageName, - chosenActivity.resolveInfo.activityInfo.name); - - Intent choiceIntent = new Intent(mIntent); - choiceIntent.setComponent(chosenName); - - if (mActivityChoserModelPolicy != null) { - // Do not allow the policy to change the intent. - Intent choiceIntentCopy = new Intent(choiceIntent); - final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this, - choiceIntentCopy); - if (handled) { - return null; - } - } - - HistoricalRecord historicalRecord = new HistoricalRecord(chosenName, - System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT); - addHisoricalRecord(historicalRecord); - - return choiceIntent; - } - - /** - * Sets the listener for choosing an activity. - * - * @param listener The listener. - */ - public void setOnChooseActivityListener(OnChooseActivityListener listener) { - mActivityChoserModelPolicy = listener; - } - - /** - * Gets the default activity, The default activity is defined as the one - * with highest rank i.e. the first one in the list of activities that can - * handle the intent. - * - * @return The default activity, null id not activities. - * - * @see #getActivity(int) - */ - public ResolveInfo getDefaultActivity() { - synchronized (mInstanceLock) { - if (!mActivites.isEmpty()) { - return mActivites.get(0).resolveInfo; - } - } - return null; - } - - /** - * Sets the default activity. The default activity is set by adding a - * historical record with weight high enough that this activity will - * become the highest ranked. Such a strategy guarantees that the default - * will eventually change if not used. Also the weight of the record for - * setting a default is inflated with a constant amount to guarantee that - * it will stay as default for awhile. - * - * @param index The index of the activity to set as default. - */ - public void setDefaultActivity(int index) { - ActivityResolveInfo newDefaultActivity = mActivites.get(index); - ActivityResolveInfo oldDefaultActivity = mActivites.get(0); - - final float weight; - if (oldDefaultActivity != null) { - // Add a record with weight enough to boost the chosen at the top. - weight = oldDefaultActivity.weight - newDefaultActivity.weight - + DEFAULT_ACTIVITY_INFLATION; - } else { - weight = DEFAULT_HISTORICAL_RECORD_WEIGHT; - } - - ComponentName defaultName = new ComponentName( - newDefaultActivity.resolveInfo.activityInfo.packageName, - newDefaultActivity.resolveInfo.activityInfo.name); - HistoricalRecord historicalRecord = new HistoricalRecord(defaultName, - System.currentTimeMillis(), weight); - addHisoricalRecord(historicalRecord); - } - - /** - * Reads the history data from the backing file if the latter - * was provided. Calling this method more than once before a call - * to {@link #persistHistoricalData()} has been made has no effect. - *

- * Note: Historical data is read asynchronously and - * as soon as the reading is completed any registered - * {@link DataSetObserver}s will be notified. Also no historical - * data is read until this method is invoked. - *

- */ - private void readHistoricalData() { - synchronized (mInstanceLock) { - if (!mCanReadHistoricalData || !mHistoricalRecordsChanged) { - return; - } - mCanReadHistoricalData = false; - mReadShareHistoryCalled = true; - if (!TextUtils.isEmpty(mHistoryFileName)) { - /*AsyncTask.*/SERIAL_EXECUTOR.execute(new HistoryLoader()); - } - } - } - - private static final Executor SERIAL_EXECUTOR = Executors.newSingleThreadExecutor(); - - /** - * Persists the history data to the backing file if the latter - * was provided. Calling this method before a call to {@link #readHistoricalData()} - * throws an exception. Calling this method more than one without choosing an - * activity has not effect. - * - * @throws IllegalStateException If this method is called before a call to - * {@link #readHistoricalData()}. - */ - private void persistHistoricalData() { - synchronized (mInstanceLock) { - if (!mReadShareHistoryCalled) { - throw new IllegalStateException("No preceding call to #readHistoricalData"); - } - if (!mHistoricalRecordsChanged) { - return; - } - mHistoricalRecordsChanged = false; - mCanReadHistoricalData = true; - if (!TextUtils.isEmpty(mHistoryFileName)) { - /*AsyncTask.*/SERIAL_EXECUTOR.execute(new HistoryPersister()); - } - } - } - - /** - * Sets the sorter for ordering activities based on historical data and an intent. - * - * @param activitySorter The sorter. - * - * @see ActivitySorter - */ - public void setActivitySorter(ActivitySorter activitySorter) { - synchronized (mInstanceLock) { - if (mActivitySorter == activitySorter) { - return; - } - mActivitySorter = activitySorter; - sortActivities(); - } - } - - /** - * Sorts the activities based on history and an intent. If - * a sorter is not specified this a default implementation is used. - * - * @see #setActivitySorter(ActivitySorter) - */ - private void sortActivities() { - synchronized (mInstanceLock) { - if (mActivitySorter != null && !mActivites.isEmpty()) { - mActivitySorter.sort(mIntent, mActivites, - Collections.unmodifiableList(mHistoricalRecords)); - notifyChanged(); - } - } - } - - /** - * Sets the maximal size of the historical data. Defaults to - * {@link #DEFAULT_HISTORY_MAX_LENGTH} - *

- * Note: Setting this property will immediately - * enforce the specified max history size by dropping enough old - * historical records to enforce the desired size. Thus, any - * records that exceed the history size will be discarded and - * irreversibly lost. - *

- * - * @param historyMaxSize The max history size. - */ - public void setHistoryMaxSize(int historyMaxSize) { - synchronized (mInstanceLock) { - if (mHistoryMaxSize == historyMaxSize) { - return; - } - mHistoryMaxSize = historyMaxSize; - pruneExcessiveHistoricalRecordsLocked(); - sortActivities(); - } - } - - /** - * Gets the history max size. - * - * @return The history max size. - */ - public int getHistoryMaxSize() { - synchronized (mInstanceLock) { - return mHistoryMaxSize; - } - } - - /** - * Gets the history size. - * - * @return The history size. - */ - public int getHistorySize() { - synchronized (mInstanceLock) { - return mHistoricalRecords.size(); - } - } - - /** - * Adds a historical record. - * - * @param historicalRecord The record to add. - * @return True if the record was added. - */ - private boolean addHisoricalRecord(HistoricalRecord historicalRecord) { - synchronized (mInstanceLock) { - final boolean added = mHistoricalRecords.add(historicalRecord); - if (added) { - mHistoricalRecordsChanged = true; - pruneExcessiveHistoricalRecordsLocked(); - persistHistoricalData(); - sortActivities(); - } - return added; - } - } - - /** - * Prunes older excessive records to guarantee {@link #mHistoryMaxSize}. - */ - private void pruneExcessiveHistoricalRecordsLocked() { - List choiceRecords = mHistoricalRecords; - final int pruneCount = choiceRecords.size() - mHistoryMaxSize; - if (pruneCount <= 0) { - return; - } - mHistoricalRecordsChanged = true; - for (int i = 0; i < pruneCount; i++) { - HistoricalRecord prunedRecord = choiceRecords.remove(0); - if (DEBUG) { - Log.i(LOG_TAG, "Pruned: " + prunedRecord); - } - } - } - - /** - * Loads the activities. - */ - private void loadActivitiesLocked() { - mActivites.clear(); - if (mIntent != null) { - List resolveInfos = - mContext.getPackageManager().queryIntentActivities(mIntent, 0); - final int resolveInfoCount = resolveInfos.size(); - for (int i = 0; i < resolveInfoCount; i++) { - ResolveInfo resolveInfo = resolveInfos.get(i); - mActivites.add(new ActivityResolveInfo(resolveInfo)); - } - sortActivities(); - } else { - notifyChanged(); - } - } - - /** - * Represents a record in the history. - */ - public final static class HistoricalRecord { - - /** - * The activity name. - */ - public final ComponentName activity; - - /** - * The choice time. - */ - public final long time; - - /** - * The record weight. - */ - public final float weight; - - /** - * Creates a new instance. - * - * @param activityName The activity component name flattened to string. - * @param time The time the activity was chosen. - * @param weight The weight of the record. - */ - public HistoricalRecord(String activityName, long time, float weight) { - this(ComponentName.unflattenFromString(activityName), time, weight); - } - - /** - * Creates a new instance. - * - * @param activityName The activity name. - * @param time The time the activity was chosen. - * @param weight The weight of the record. - */ - public HistoricalRecord(ComponentName activityName, long time, float weight) { - this.activity = activityName; - this.time = time; - this.weight = weight; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((activity == null) ? 0 : activity.hashCode()); - result = prime * result + (int) (time ^ (time >>> 32)); - result = prime * result + Float.floatToIntBits(weight); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - HistoricalRecord other = (HistoricalRecord) obj; - if (activity == null) { - if (other.activity != null) { - return false; - } - } else if (!activity.equals(other.activity)) { - return false; - } - if (time != other.time) { - return false; - } - if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) { - return false; - } - return true; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("["); - builder.append("; activity:").append(activity); - builder.append("; time:").append(time); - builder.append("; weight:").append(new BigDecimal(weight)); - builder.append("]"); - return builder.toString(); - } - } - - /** - * Represents an activity. - */ - public final class ActivityResolveInfo implements Comparable { - - /** - * The {@link ResolveInfo} of the activity. - */ - public final ResolveInfo resolveInfo; - - /** - * Weight of the activity. Useful for sorting. - */ - public float weight; - - /** - * Creates a new instance. - * - * @param resolveInfo activity {@link ResolveInfo}. - */ - public ActivityResolveInfo(ResolveInfo resolveInfo) { - this.resolveInfo = resolveInfo; - } - - @Override - public int hashCode() { - return 31 + Float.floatToIntBits(weight); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ActivityResolveInfo other = (ActivityResolveInfo) obj; - if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) { - return false; - } - return true; - } - - public int compareTo(ActivityResolveInfo another) { - return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("["); - builder.append("resolveInfo:").append(resolveInfo.toString()); - builder.append("; weight:").append(new BigDecimal(weight)); - builder.append("]"); - return builder.toString(); - } - } - - /** - * Default activity sorter implementation. - */ - private final class DefaultSorter implements ActivitySorter { - private static final float WEIGHT_DECAY_COEFFICIENT = 0.95f; - - private final Map mPackageNameToActivityMap = - new HashMap(); - - public void sort(Intent intent, List activities, - List historicalRecords) { - Map packageNameToActivityMap = - mPackageNameToActivityMap; - packageNameToActivityMap.clear(); - - final int activityCount = activities.size(); - for (int i = 0; i < activityCount; i++) { - ActivityResolveInfo activity = activities.get(i); - activity.weight = 0.0f; - String packageName = activity.resolveInfo.activityInfo.packageName; - packageNameToActivityMap.put(packageName, activity); - } - - final int lastShareIndex = historicalRecords.size() - 1; - float nextRecordWeight = 1; - for (int i = lastShareIndex; i >= 0; i--) { - HistoricalRecord historicalRecord = historicalRecords.get(i); - String packageName = historicalRecord.activity.getPackageName(); - ActivityResolveInfo activity = packageNameToActivityMap.get(packageName); - if (activity != null) { - activity.weight += historicalRecord.weight * nextRecordWeight; - nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT; - } - } - - Collections.sort(activities); - - if (DEBUG) { - for (int i = 0; i < activityCount; i++) { - Log.i(LOG_TAG, "Sorted: " + activities.get(i)); - } - } - } - } - - /** - * Command for reading the historical records from a file off the UI thread. - */ - private final class HistoryLoader implements Runnable { - - public void run() { - FileInputStream fis = null; - try { - fis = mContext.openFileInput(mHistoryFileName); - } catch (FileNotFoundException fnfe) { - if (DEBUG) { - Log.i(LOG_TAG, "Could not open historical records file: " + mHistoryFileName); - } - return; - } - try { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(fis, null); - - int type = XmlPullParser.START_DOCUMENT; - while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { - type = parser.next(); - } - - if (!TAG_HISTORICAL_RECORDS.equals(parser.getName())) { - throw new XmlPullParserException("Share records file does not start with " - + TAG_HISTORICAL_RECORDS + " tag."); - } - - List readRecords = new ArrayList(); - - while (true) { - type = parser.next(); - if (type == XmlPullParser.END_DOCUMENT) { - break; - } - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - String nodeName = parser.getName(); - if (!TAG_HISTORICAL_RECORD.equals(nodeName)) { - throw new XmlPullParserException("Share records file not well-formed."); - } - - String activity = parser.getAttributeValue(null, ATTRIBUTE_ACTIVITY); - final long time = - Long.parseLong(parser.getAttributeValue(null, ATTRIBUTE_TIME)); - final float weight = - Float.parseFloat(parser.getAttributeValue(null, ATTRIBUTE_WEIGHT)); - - HistoricalRecord readRecord = new HistoricalRecord(activity, time, - weight); - readRecords.add(readRecord); - - if (DEBUG) { - Log.i(LOG_TAG, "Read " + readRecord.toString()); - } - } - - if (DEBUG) { - Log.i(LOG_TAG, "Read " + readRecords.size() + " historical records."); - } - - synchronized (mInstanceLock) { - Set uniqueShareRecords = - new LinkedHashSet(readRecords); - - // Make sure no duplicates. Example: Read a file with - // one record, add one record, persist the two records, - // add a record, read the persisted records - the - // read two records should not be added again. - List historicalRecords = mHistoricalRecords; - final int historicalRecordsCount = historicalRecords.size(); - for (int i = historicalRecordsCount - 1; i >= 0; i--) { - HistoricalRecord historicalRecord = historicalRecords.get(i); - uniqueShareRecords.add(historicalRecord); - } - - if (historicalRecords.size() == uniqueShareRecords.size()) { - return; - } - - // Make sure the oldest records go to the end. - historicalRecords.clear(); - historicalRecords.addAll(uniqueShareRecords); - - mHistoricalRecordsChanged = true; - - // Do this on the client thread since the client may be on the UI - // thread, wait for data changes which happen during sorting, and - // perform UI modification based on the data change. - mHandler.post(new Runnable() { - public void run() { - pruneExcessiveHistoricalRecordsLocked(); - sortActivities(); - } - }); - } - } catch (XmlPullParserException xppe) { - Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, xppe); - } catch (IOException ioe) { - Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, ioe); - } finally { - if (fis != null) { - try { - fis.close(); - } catch (IOException ioe) { - /* ignore */ - } - } - } - } - } - - /** - * Command for persisting the historical records to a file off the UI thread. - */ - private final class HistoryPersister implements Runnable { - - public void run() { - FileOutputStream fos = null; - List records = null; - - synchronized (mInstanceLock) { - records = new ArrayList(mHistoricalRecords); - } - - try { - fos = mContext.openFileOutput(mHistoryFileName, Context.MODE_PRIVATE); - } catch (FileNotFoundException fnfe) { - Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, fnfe); - return; - } - - XmlSerializer serializer = Xml.newSerializer(); - - try { - serializer.setOutput(fos, null); - serializer.startDocument("UTF-8", true); - serializer.startTag(null, TAG_HISTORICAL_RECORDS); - - final int recordCount = records.size(); - for (int i = 0; i < recordCount; i++) { - HistoricalRecord record = records.remove(0); - serializer.startTag(null, TAG_HISTORICAL_RECORD); - serializer.attribute(null, ATTRIBUTE_ACTIVITY, record.activity.flattenToString()); - serializer.attribute(null, ATTRIBUTE_TIME, String.valueOf(record.time)); - serializer.attribute(null, ATTRIBUTE_WEIGHT, String.valueOf(record.weight)); - serializer.endTag(null, TAG_HISTORICAL_RECORD); - if (DEBUG) { - Log.i(LOG_TAG, "Wrote " + record.toString()); - } - } - - serializer.endTag(null, TAG_HISTORICAL_RECORDS); - serializer.endDocument(); - - if (DEBUG) { - Log.i(LOG_TAG, "Wrote " + recordCount + " historical records."); - } - } catch (IllegalArgumentException iae) { - Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, iae); - } catch (IllegalStateException ise) { - Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ise); - } catch (IOException ioe) { - Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ioe); - } finally { - if (fos != null) { - try { - fos.close(); - } catch (IOException e) { - /* ignore */ - } - } - } - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java deleted file mode 100644 index e19ea9e9e..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java +++ /dev/null @@ -1,827 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.widget; - -import android.os.Build; -import com.actionbarsherlock.R; -import com.actionbarsherlock.internal.widget.IcsLinearLayout; -import com.actionbarsherlock.internal.widget.IcsListPopupWindow; -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.widget.ActivityChooserModel.ActivityChooserModelClient; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.PopupWindow; -import android.widget.TextView; - -/** - * This class is a view for choosing an activity for handling a given {@link Intent}. - *

- * The view is composed of two adjacent buttons: - *

    - *
  • - * The left button is an immediate action and allows one click activity choosing. - * Tapping this button immediately executes the intent without requiring any further - * user input. Long press on this button shows a popup for changing the default - * activity. - *
  • - *
  • - * The right button is an overflow action and provides an optimized menu - * of additional activities. Tapping this button shows a popup anchored to this - * view, listing the most frequently used activities. This list is initially - * limited to a small number of items in frequency used order. The last item, - * "Show all..." serves as an affordance to display all available activities. - *
  • - *
- *

- * - * @hide - */ -class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient { - - /** - * An adapter for displaying the activities in an {@link AdapterView}. - */ - private final ActivityChooserViewAdapter mAdapter; - - /** - * Implementation of various interfaces to avoid publishing them in the APIs. - */ - private final Callbacks mCallbacks; - - /** - * The content of this view. - */ - private final IcsLinearLayout mActivityChooserContent; - - /** - * Stores the background drawable to allow hiding and latter showing. - */ - private final Drawable mActivityChooserContentBackground; - - /** - * The expand activities action button; - */ - private final FrameLayout mExpandActivityOverflowButton; - - /** - * The image for the expand activities action button; - */ - private final ImageView mExpandActivityOverflowButtonImage; - - /** - * The default activities action button; - */ - private final FrameLayout mDefaultActivityButton; - - /** - * The image for the default activities action button; - */ - private final ImageView mDefaultActivityButtonImage; - - /** - * The maximal width of the list popup. - */ - private final int mListPopupMaxWidth; - - /** - * The ActionProvider hosting this view, if applicable. - */ - ActionProvider mProvider; - - /** - * Observer for the model data. - */ - private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { - - @Override - public void onChanged() { - super.onChanged(); - mAdapter.notifyDataSetChanged(); - } - @Override - public void onInvalidated() { - super.onInvalidated(); - mAdapter.notifyDataSetInvalidated(); - } - }; - - private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (isShowingPopup()) { - if (!isShown()) { - getListPopupWindow().dismiss(); - } else { - getListPopupWindow().show(); - if (mProvider != null) { - mProvider.subUiVisibilityChanged(true); - } - } - } - } - }; - - /** - * Popup window for showing the activity overflow list. - */ - private IcsListPopupWindow mListPopupWindow; - - /** - * Listener for the dismissal of the popup/alert. - */ - private PopupWindow.OnDismissListener mOnDismissListener; - - /** - * Flag whether a default activity currently being selected. - */ - private boolean mIsSelectingDefaultActivity; - - /** - * The count of activities in the popup. - */ - private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT; - - /** - * Flag whether this view is attached to a window. - */ - private boolean mIsAttachedToWindow; - - /** - * String resource for formatting content description of the default target. - */ - private int mDefaultActionButtonContentDescription; - - private final Context mContext; - - /** - * Create a new instance. - * - * @param context The application environment. - */ - public ActivityChooserView(Context context) { - this(context, null); - } - - /** - * Create a new instance. - * - * @param context The application environment. - * @param attrs A collection of attributes. - */ - public ActivityChooserView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - /** - * Create a new instance. - * - * @param context The application environment. - * @param attrs A collection of attributes. - * @param defStyle The default style to apply to this view. - */ - public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mContext = context; - - TypedArray attributesArray = context.obtainStyledAttributes(attrs, - R.styleable.SherlockActivityChooserView, defStyle, 0); - - mInitialActivityCount = attributesArray.getInt( - R.styleable.SherlockActivityChooserView_initialActivityCount, - ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT); - - Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable( - R.styleable.SherlockActivityChooserView_expandActivityOverflowButtonDrawable); - - attributesArray.recycle(); - - LayoutInflater inflater = LayoutInflater.from(mContext); - inflater.inflate(R.layout.abs__activity_chooser_view, this, true); - - mCallbacks = new Callbacks(); - - mActivityChooserContent = (IcsLinearLayout) findViewById(R.id.abs__activity_chooser_view_content); - mActivityChooserContentBackground = mActivityChooserContent.getBackground(); - - mDefaultActivityButton = (FrameLayout) findViewById(R.id.abs__default_activity_button); - mDefaultActivityButton.setOnClickListener(mCallbacks); - mDefaultActivityButton.setOnLongClickListener(mCallbacks); - mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.abs__image); - - mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.abs__expand_activities_button); - mExpandActivityOverflowButton.setOnClickListener(mCallbacks); - mExpandActivityOverflowButtonImage = - (ImageView) mExpandActivityOverflowButton.findViewById(R.id.abs__image); - mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable); - - mAdapter = new ActivityChooserViewAdapter(); - mAdapter.registerDataSetObserver(new DataSetObserver() { - @Override - public void onChanged() { - super.onChanged(); - updateAppearance(); - } - }); - - Resources resources = context.getResources(); - mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2, - resources.getDimensionPixelSize(R.dimen.abs__config_prefDialogWidth)); - } - - /** - * {@inheritDoc} - */ - public void setActivityChooserModel(ActivityChooserModel dataModel) { - mAdapter.setDataModel(dataModel); - if (isShowingPopup()) { - dismissPopup(); - showPopup(); - } - } - - /** - * Sets the background for the button that expands the activity - * overflow list. - * - * Note: Clients would like to set this drawable - * as a clue about the action the chosen activity will perform. For - * example, if a share activity is to be chosen the drawable should - * give a clue that sharing is to be performed. - * - * @param drawable The drawable. - */ - public void setExpandActivityOverflowButtonDrawable(Drawable drawable) { - mExpandActivityOverflowButtonImage.setImageDrawable(drawable); - } - - /** - * Sets the content description for the button that expands the activity - * overflow list. - * - * description as a clue about the action performed by the button. - * For example, if a share activity is to be chosen the content - * description should be something like "Share with". - * - * @param resourceId The content description resource id. - */ - public void setExpandActivityOverflowButtonContentDescription(int resourceId) { - CharSequence contentDescription = mContext.getString(resourceId); - mExpandActivityOverflowButtonImage.setContentDescription(contentDescription); - } - - /** - * Set the provider hosting this view, if applicable. - * @hide Internal use only - */ - public void setProvider(ActionProvider provider) { - mProvider = provider; - } - - /** - * Shows the popup window with activities. - * - * @return True if the popup was shown, false if already showing. - */ - public boolean showPopup() { - if (isShowingPopup() || !mIsAttachedToWindow) { - return false; - } - mIsSelectingDefaultActivity = false; - showPopupUnchecked(mInitialActivityCount); - return true; - } - - /** - * Shows the popup no matter if it was already showing. - * - * @param maxActivityCount The max number of activities to display. - */ - private void showPopupUnchecked(int maxActivityCount) { - if (mAdapter.getDataModel() == null) { - throw new IllegalStateException("No data model. Did you call #setDataModel?"); - } - - getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener); - - final boolean defaultActivityButtonShown = - mDefaultActivityButton.getVisibility() == VISIBLE; - - final int activityCount = mAdapter.getActivityCount(); - final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0; - if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED - && activityCount > maxActivityCount + maxActivityCountOffset) { - mAdapter.setShowFooterView(true); - mAdapter.setMaxActivityCount(maxActivityCount - 1); - } else { - mAdapter.setShowFooterView(false); - mAdapter.setMaxActivityCount(maxActivityCount); - } - - IcsListPopupWindow popupWindow = getListPopupWindow(); - if (!popupWindow.isShowing()) { - if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) { - mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown); - } else { - mAdapter.setShowDefaultActivity(false, false); - } - final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth); - popupWindow.setContentWidth(contentWidth); - popupWindow.show(); - if (mProvider != null) { - mProvider.subUiVisibilityChanged(true); - } - popupWindow.getListView().setContentDescription(mContext.getString( - R.string.abs__activitychooserview_choose_application)); - } - } - - /** - * Dismisses the popup window with activities. - * - * @return True if dismissed, false if already dismissed. - */ - public boolean dismissPopup() { - if (isShowingPopup()) { - getListPopupWindow().dismiss(); - ViewTreeObserver viewTreeObserver = getViewTreeObserver(); - if (viewTreeObserver.isAlive()) { - viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); - } - } - return true; - } - - /** - * Gets whether the popup window with activities is shown. - * - * @return True if the popup is shown. - */ - public boolean isShowingPopup() { - return getListPopupWindow().isShowing(); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - ActivityChooserModel dataModel = mAdapter.getDataModel(); - if (dataModel != null) { - dataModel.registerObserver(mModelDataSetOberver); - } - mIsAttachedToWindow = true; - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - ActivityChooserModel dataModel = mAdapter.getDataModel(); - if (dataModel != null) { - try { - dataModel.unregisterObserver(mModelDataSetOberver); - } catch (IllegalStateException e) { - //Oh, well... fixes issue #557 - } - } - ViewTreeObserver viewTreeObserver = getViewTreeObserver(); - if (viewTreeObserver.isAlive()) { - viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); - } - mIsAttachedToWindow = false; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - View child = mActivityChooserContent; - // If the default action is not visible we want to be as tall as the - // ActionBar so if this widget is used in the latter it will look as - // a normal action button. - if (mDefaultActivityButton.getVisibility() != VISIBLE) { - heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), - MeasureSpec.EXACTLY); - } - measureChild(child, widthMeasureSpec, heightMeasureSpec); - setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight()); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mActivityChooserContent.layout(0, 0, right - left, bottom - top); - if (getListPopupWindow().isShowing()) { - showPopupUnchecked(mAdapter.getMaxActivityCount()); - } else { - dismissPopup(); - } - } - - public ActivityChooserModel getDataModel() { - return mAdapter.getDataModel(); - } - - /** - * Sets a listener to receive a callback when the popup is dismissed. - * - * @param listener The listener to be notified. - */ - public void setOnDismissListener(PopupWindow.OnDismissListener listener) { - mOnDismissListener = listener; - } - - /** - * Sets the initial count of items shown in the activities popup - * i.e. the items before the popup is expanded. This is an upper - * bound since it is not guaranteed that such number of intent - * handlers exist. - * - * @param itemCount The initial popup item count. - */ - public void setInitialActivityCount(int itemCount) { - mInitialActivityCount = itemCount; - } - - /** - * Sets a content description of the default action button. This - * resource should be a string taking one formatting argument and - * will be used for formatting the content description of the button - * dynamically as the default target changes. For example, a resource - * pointing to the string "share with %1$s" will result in a content - * description "share with Bluetooth" for the Bluetooth activity. - * - * @param resourceId The resource id. - */ - public void setDefaultActionButtonContentDescription(int resourceId) { - mDefaultActionButtonContentDescription = resourceId; - } - - /** - * Gets the list popup window which is lazily initialized. - * - * @return The popup. - */ - private IcsListPopupWindow getListPopupWindow() { - if (mListPopupWindow == null) { - mListPopupWindow = new IcsListPopupWindow(getContext()); - mListPopupWindow.setAdapter(mAdapter); - mListPopupWindow.setAnchorView(ActivityChooserView.this); - mListPopupWindow.setModal(true); - mListPopupWindow.setOnItemClickListener(mCallbacks); - mListPopupWindow.setOnDismissListener(mCallbacks); - } - return mListPopupWindow; - } - - /** - * Updates the buttons state. - */ - private void updateAppearance() { - // Expand overflow button. - if (mAdapter.getCount() > 0) { - mExpandActivityOverflowButton.setEnabled(true); - } else { - mExpandActivityOverflowButton.setEnabled(false); - } - // Default activity button. - final int activityCount = mAdapter.getActivityCount(); - final int historySize = mAdapter.getHistorySize(); - if (activityCount > 0 && historySize > 0) { - mDefaultActivityButton.setVisibility(VISIBLE); - ResolveInfo activity = mAdapter.getDefaultActivity(); - PackageManager packageManager = mContext.getPackageManager(); - mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager)); - if (mDefaultActionButtonContentDescription != 0) { - CharSequence label = activity.loadLabel(packageManager); - String contentDescription = mContext.getString( - mDefaultActionButtonContentDescription, label); - mDefaultActivityButton.setContentDescription(contentDescription); - } - } else { - mDefaultActivityButton.setVisibility(View.GONE); - } - // Activity chooser content. - if (mDefaultActivityButton.getVisibility() == VISIBLE) { - mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground); - } else { - mActivityChooserContent.setBackgroundDrawable(null); - mActivityChooserContent.setPadding(0, 0, 0, 0); - } - } - - /** - * Interface implementation to avoid publishing them in the APIs. - */ - private class Callbacks implements AdapterView.OnItemClickListener, - View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener { - - // AdapterView#OnItemClickListener - public void onItemClick(AdapterView parent, View view, int position, long id) { - ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter(); - final int itemViewType = adapter.getItemViewType(position); - switch (itemViewType) { - case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: { - showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED); - } break; - case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: { - dismissPopup(); - if (mIsSelectingDefaultActivity) { - // The item at position zero is the default already. - if (position > 0) { - mAdapter.getDataModel().setDefaultActivity(position); - } - } else { - // If the default target is not shown in the list, the first - // item in the model is default action => adjust index - position = mAdapter.getShowDefaultActivity() ? position : position + 1; - Intent launchIntent = mAdapter.getDataModel().chooseActivity(position); - if (launchIntent != null) { - mContext.startActivity(launchIntent); - } - } - } break; - default: - throw new IllegalArgumentException(); - } - } - - // View.OnClickListener - public void onClick(View view) { - if (view == mDefaultActivityButton) { - dismissPopup(); - ResolveInfo defaultActivity = mAdapter.getDefaultActivity(); - final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity); - Intent launchIntent = mAdapter.getDataModel().chooseActivity(index); - if (launchIntent != null) { - mContext.startActivity(launchIntent); - } - } else if (view == mExpandActivityOverflowButton) { - mIsSelectingDefaultActivity = false; - showPopupUnchecked(mInitialActivityCount); - } else { - throw new IllegalArgumentException(); - } - } - - // OnLongClickListener#onLongClick - @Override - public boolean onLongClick(View view) { - if (view == mDefaultActivityButton) { - if (mAdapter.getCount() > 0) { - mIsSelectingDefaultActivity = true; - showPopupUnchecked(mInitialActivityCount); - } - } else { - throw new IllegalArgumentException(); - } - return true; - } - - // PopUpWindow.OnDismissListener#onDismiss - public void onDismiss() { - notifyOnDismissListener(); - if (mProvider != null) { - mProvider.subUiVisibilityChanged(false); - } - } - - private void notifyOnDismissListener() { - if (mOnDismissListener != null) { - mOnDismissListener.onDismiss(); - } - } - } - - private static class SetActivated { - public static void invoke(View view, boolean activated) { - view.setActivated(activated); - } - } - - private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; - - /** - * Adapter for backing the list of activities shown in the popup. - */ - private class ActivityChooserViewAdapter extends BaseAdapter { - - public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE; - - public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4; - - private static final int ITEM_VIEW_TYPE_ACTIVITY = 0; - - private static final int ITEM_VIEW_TYPE_FOOTER = 1; - - private static final int ITEM_VIEW_TYPE_COUNT = 3; - - private ActivityChooserModel mDataModel; - - private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT; - - private boolean mShowDefaultActivity; - - private boolean mHighlightDefaultActivity; - - private boolean mShowFooterView; - - public void setDataModel(ActivityChooserModel dataModel) { - ActivityChooserModel oldDataModel = mAdapter.getDataModel(); - if (oldDataModel != null && isShown()) { - try { - oldDataModel.unregisterObserver(mModelDataSetOberver); - } catch (IllegalStateException e) { - //Oh, well... fixes issue #557 - } - } - mDataModel = dataModel; - if (dataModel != null && isShown()) { - dataModel.registerObserver(mModelDataSetOberver); - } - notifyDataSetChanged(); - } - - @Override - public int getItemViewType(int position) { - if (mShowFooterView && position == getCount() - 1) { - return ITEM_VIEW_TYPE_FOOTER; - } else { - return ITEM_VIEW_TYPE_ACTIVITY; - } - } - - @Override - public int getViewTypeCount() { - return ITEM_VIEW_TYPE_COUNT; - } - - public int getCount() { - int count = 0; - int activityCount = mDataModel.getActivityCount(); - if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { - activityCount--; - } - count = Math.min(activityCount, mMaxActivityCount); - if (mShowFooterView) { - count++; - } - return count; - } - - public Object getItem(int position) { - final int itemViewType = getItemViewType(position); - switch (itemViewType) { - case ITEM_VIEW_TYPE_FOOTER: - return null; - case ITEM_VIEW_TYPE_ACTIVITY: - if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { - position++; - } - return mDataModel.getActivity(position); - default: - throw new IllegalArgumentException(); - } - } - - public long getItemId(int position) { - return position; - } - - public View getView(int position, View convertView, ViewGroup parent) { - final int itemViewType = getItemViewType(position); - switch (itemViewType) { - case ITEM_VIEW_TYPE_FOOTER: - if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) { - convertView = LayoutInflater.from(getContext()).inflate( - R.layout.abs__activity_chooser_view_list_item, parent, false); - convertView.setId(ITEM_VIEW_TYPE_FOOTER); - TextView titleView = (TextView) convertView.findViewById(R.id.abs__title); - titleView.setText(mContext.getString( - R.string.abs__activity_chooser_view_see_all)); - } - return convertView; - case ITEM_VIEW_TYPE_ACTIVITY: - if (convertView == null || convertView.getId() != R.id.abs__list_item) { - convertView = LayoutInflater.from(getContext()).inflate( - R.layout.abs__activity_chooser_view_list_item, parent, false); - } - PackageManager packageManager = mContext.getPackageManager(); - // Set the icon - ImageView iconView = (ImageView) convertView.findViewById(R.id.abs__icon); - ResolveInfo activity = (ResolveInfo) getItem(position); - iconView.setImageDrawable(activity.loadIcon(packageManager)); - // Set the title. - TextView titleView = (TextView) convertView.findViewById(R.id.abs__title); - titleView.setText(activity.loadLabel(packageManager)); - if (IS_HONEYCOMB) { - // Highlight the default. - if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) { - SetActivated.invoke(convertView, true); - } else { - SetActivated.invoke(convertView, false); - } - } - return convertView; - default: - throw new IllegalArgumentException(); - } - } - - public int measureContentWidth() { - // The user may have specified some of the target not to be shown but we - // want to measure all of them since after expansion they should fit. - final int oldMaxActivityCount = mMaxActivityCount; - mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED; - - int contentWidth = 0; - View itemView = null; - - final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - final int count = getCount(); - - for (int i = 0; i < count; i++) { - itemView = getView(i, itemView, null); - itemView.measure(widthMeasureSpec, heightMeasureSpec); - contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth()); - } - - mMaxActivityCount = oldMaxActivityCount; - - return contentWidth; - } - - public void setMaxActivityCount(int maxActivityCount) { - if (mMaxActivityCount != maxActivityCount) { - mMaxActivityCount = maxActivityCount; - notifyDataSetChanged(); - } - } - - public ResolveInfo getDefaultActivity() { - return mDataModel.getDefaultActivity(); - } - - public void setShowFooterView(boolean showFooterView) { - if (mShowFooterView != showFooterView) { - mShowFooterView = showFooterView; - notifyDataSetChanged(); - } - } - - public int getActivityCount() { - return mDataModel.getActivityCount(); - } - - public int getHistorySize() { - return mDataModel.getHistorySize(); - } - - public int getMaxActivityCount() { - return mMaxActivityCount; - } - - public ActivityChooserModel getDataModel() { - return mDataModel; - } - - public void setShowDefaultActivity(boolean showDefaultActivity, - boolean highlightDefaultActivity) { - if (mShowDefaultActivity != showDefaultActivity - || mHighlightDefaultActivity != highlightDefaultActivity) { - mShowDefaultActivity = showDefaultActivity; - mHighlightDefaultActivity = highlightDefaultActivity; - notifyDataSetChanged(); - } - } - - public boolean getShowDefaultActivity() { - return mShowDefaultActivity; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java deleted file mode 100644 index c9e7897d4..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java +++ /dev/null @@ -1,1811 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.widget; - -import android.app.PendingIntent; -import android.app.SearchManager; -import android.app.SearchableInfo; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.database.Cursor; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.ResultReceiver; -import android.speech.RecognizerIntent; -import android.support.v4.view.KeyEventCompat; -import android.support.v4.widget.CursorAdapter; -import android.text.Editable; -import android.text.InputType; -import android.text.Spannable; -import android.text.SpannableStringBuilder; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.text.style.ImageSpan; -import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewTreeObserver; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.AutoCompleteTextView; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ListView; -import android.widget.TextView; -import android.widget.TextView.OnEditorActionListener; -import com.actionbarsherlock.R; -import com.actionbarsherlock.view.CollapsibleActionView; - -import java.lang.reflect.Method; -import java.util.WeakHashMap; - -import static com.actionbarsherlock.widget.SuggestionsAdapter.getColumnString; - -/** - * A widget that provides a user interface for the user to enter a search query and submit a request - * to a search provider. Shows a list of query suggestions or results, if available, and allows the - * user to pick a suggestion or result to launch into. - * - *

- * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it - * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean) - * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done. - *

- *

- * If you want the search field to always be visible, then call setIconifiedByDefault(false). - *

- * - *
- *

Developer Guides

- *

For information about using {@code SearchView}, read the - * Search developer guide.

- *
- * - * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW - * @attr ref android.R.styleable#SearchView_iconifiedByDefault - * @attr ref android.R.styleable#SearchView_imeOptions - * @attr ref android.R.styleable#SearchView_inputType - * @attr ref android.R.styleable#SearchView_maxWidth - * @attr ref android.R.styleable#SearchView_queryHint - */ -public class SearchView extends LinearLayout implements CollapsibleActionView { - - private static final boolean DBG = false; - private static final String LOG_TAG = "SearchView"; - - /** - * Private constant for removing the microphone in the keyboard. - */ - private static final String IME_OPTION_NO_MICROPHONE = "nm"; - - private OnQueryTextListener mOnQueryChangeListener; - private OnCloseListener mOnCloseListener; - private OnFocusChangeListener mOnQueryTextFocusChangeListener; - private OnSuggestionListener mOnSuggestionListener; - private OnClickListener mOnSearchClickListener; - - private boolean mIconifiedByDefault; - private boolean mIconified; - private CursorAdapter mSuggestionsAdapter; - private View mSearchButton; - private View mSubmitButton; - private View mSearchPlate; - private View mSubmitArea; - private ImageView mCloseButton; - private View mSearchEditFrame; - private View mVoiceButton; - private SearchAutoComplete mQueryTextView; - private View mDropDownAnchor; - private ImageView mSearchHintIcon; - private boolean mSubmitButtonEnabled; - private CharSequence mQueryHint; - private boolean mQueryRefinement; - private boolean mClearingFocus; - private int mMaxWidth; - private boolean mVoiceButtonEnabled; - private CharSequence mOldQueryText; - private CharSequence mUserQuery; - private boolean mExpandedInActionView; - private int mCollapsedImeOptions; - - private SearchableInfo mSearchable; - private Bundle mAppSearchData; - - /* - * SearchView can be set expanded before the IME is ready to be shown during - * initial UI setup. The show operation is asynchronous to account for this. - */ - private Runnable mShowImeRunnable = new Runnable() { - public void run() { - InputMethodManager imm = (InputMethodManager) - getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - - if (imm != null) { - showSoftInputUnchecked(SearchView.this, imm, 0); - } - } - }; - - private Runnable mUpdateDrawableStateRunnable = new Runnable() { - public void run() { - updateFocusedState(); - } - }; - - private Runnable mReleaseCursorRunnable = new Runnable() { - public void run() { - if (mSuggestionsAdapter != null && mSuggestionsAdapter instanceof SuggestionsAdapter) { - mSuggestionsAdapter.changeCursor(null); - } - } - }; - - // For voice searching - private final Intent mVoiceWebSearchIntent; - private final Intent mVoiceAppSearchIntent; - - // A weak map of drawables we've gotten from other packages, so we don't load them - // more than once. - private final WeakHashMap mOutsideDrawablesCache = - new WeakHashMap(); - - /** - * Callbacks for changes to the query text. - */ - public interface OnQueryTextListener { - - /** - * Called when the user submits the query. This could be due to a key press on the - * keyboard or due to pressing a submit button. - * The listener can override the standard behavior by returning true - * to indicate that it has handled the submit request. Otherwise return false to - * let the SearchView handle the submission by launching any associated intent. - * - * @param query the query text that is to be submitted - * - * @return true if the query has been handled by the listener, false to let the - * SearchView perform the default action. - */ - boolean onQueryTextSubmit(String query); - - /** - * Called when the query text is changed by the user. - * - * @param newText the new content of the query text field. - * - * @return false if the SearchView should perform the default action of showing any - * suggestions if available, true if the action was handled by the listener. - */ - boolean onQueryTextChange(String newText); - } - - public interface OnCloseListener { - - /** - * The user is attempting to close the SearchView. - * - * @return true if the listener wants to override the default behavior of clearing the - * text field and dismissing it, false otherwise. - */ - boolean onClose(); - } - - /** - * Callback interface for selection events on suggestions. These callbacks - * are only relevant when a SearchableInfo has been specified by {@link #setSearchableInfo}. - */ - public interface OnSuggestionListener { - - /** - * Called when a suggestion was selected by navigating to it. - * @param position the absolute position in the list of suggestions. - * - * @return true if the listener handles the event and wants to override the default - * behavior of possibly rewriting the query based on the selected item, false otherwise. - */ - boolean onSuggestionSelect(int position); - - /** - * Called when a suggestion was clicked. - * @param position the absolute position of the clicked item in the list of suggestions. - * - * @return true if the listener handles the event and wants to override the default - * behavior of launching any intent or submitting a search query specified on that item. - * Return false otherwise. - */ - boolean onSuggestionClick(int position); - } - - public SearchView(Context context) { - this(context, null); - } - - public SearchView(Context context, AttributeSet attrs) { - super(context, attrs); - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { - throw new IllegalStateException("SearchView is API 8+ only."); - } - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.abs__search_view, this, true); - - mSearchButton = findViewById(R.id.abs__search_button); - mQueryTextView = (SearchAutoComplete) findViewById(R.id.abs__search_src_text); - mQueryTextView.setSearchView(this); - - mSearchEditFrame = findViewById(R.id.abs__search_edit_frame); - mSearchPlate = findViewById(R.id.abs__search_plate); - mSubmitArea = findViewById(R.id.abs__submit_area); - mSubmitButton = findViewById(R.id.abs__search_go_btn); - mCloseButton = (ImageView) findViewById(R.id.abs__search_close_btn); - mVoiceButton = findViewById(R.id.abs__search_voice_btn); - mSearchHintIcon = (ImageView) findViewById(R.id.abs__search_mag_icon); - - mSearchButton.setOnClickListener(mOnClickListener); - mCloseButton.setOnClickListener(mOnClickListener); - mSubmitButton.setOnClickListener(mOnClickListener); - mVoiceButton.setOnClickListener(mOnClickListener); - mQueryTextView.setOnClickListener(mOnClickListener); - - mQueryTextView.addTextChangedListener(mTextWatcher); - mQueryTextView.setOnEditorActionListener(mOnEditorActionListener); - mQueryTextView.setOnItemClickListener(mOnItemClickListener); - mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener); - mQueryTextView.setOnKeyListener(mTextKeyListener); - // Inform any listener of focus changes - mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() { - - public void onFocusChange(View v, boolean hasFocus) { - if (mOnQueryTextFocusChangeListener != null) { - mOnQueryTextFocusChangeListener.onFocusChange(SearchView.this, hasFocus); - } - } - }); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockSearchView, 0, 0); - setIconifiedByDefault(a.getBoolean(R.styleable.SherlockSearchView_iconifiedByDefault, true)); - int maxWidth = a.getDimensionPixelSize(R.styleable.SherlockSearchView_android_maxWidth, -1); - if (maxWidth != -1) { - setMaxWidth(maxWidth); - } - CharSequence queryHint = a.getText(R.styleable.SherlockSearchView_queryHint); - if (!TextUtils.isEmpty(queryHint)) { - setQueryHint(queryHint); - } - int imeOptions = a.getInt(R.styleable.SherlockSearchView_android_imeOptions, -1); - if (imeOptions != -1) { - setImeOptions(imeOptions); - } - int inputType = a.getInt(R.styleable.SherlockSearchView_android_inputType, -1); - if (inputType != -1) { - setInputType(inputType); - } - - a.recycle(); - - boolean focusable = true; - - a = context.obtainStyledAttributes(attrs, R.styleable.SherlockView, 0, 0); - focusable = a.getBoolean(R.styleable.SherlockView_android_focusable, focusable); - a.recycle(); - setFocusable(focusable); - - // Save voice intent for later queries/launching - mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); - mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, - RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); - - mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); - mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - - mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor()); - if (mDropDownAnchor != null) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, int bottom, - int oldLeft, int oldTop, int oldRight, int oldBottom) { - adjustDropDownSizeAndPosition(); - } - }); - } else { - mDropDownAnchor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override public void onGlobalLayout() { - adjustDropDownSizeAndPosition(); - } - }); - } - } - - updateViewsVisibility(mIconifiedByDefault); - updateQueryHint(); - } - - /** - * Sets the SearchableInfo for this SearchView. Properties in the SearchableInfo are used - * to display labels, hints, suggestions, create intents for launching search results screens - * and controlling other affordances such as a voice button. - * - * @param searchable a SearchableInfo can be retrieved from the SearchManager, for a specific - * activity or a global search provider. - */ - public void setSearchableInfo(SearchableInfo searchable) { - mSearchable = searchable; - if (mSearchable != null) { - updateSearchAutoComplete(); - updateQueryHint(); - } - // Cache the voice search capability - mVoiceButtonEnabled = hasVoiceSearch(); - - if (mVoiceButtonEnabled) { - // Disable the microphone on the keyboard, as a mic is displayed near the text box - // TODO: use imeOptions to disable voice input when the new API will be available - mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); - } - updateViewsVisibility(isIconified()); - } - - /** - * Sets the APP_DATA for legacy SearchDialog use. - * @param appSearchData bundle provided by the app when launching the search dialog - * @hide - */ - public void setAppSearchData(Bundle appSearchData) { - mAppSearchData = appSearchData; - } - - /** - * Sets the IME options on the query text field. - * - * @see TextView#setImeOptions(int) - * @param imeOptions the options to set on the query text field - * - * @attr ref android.R.styleable#SearchView_imeOptions - */ - public void setImeOptions(int imeOptions) { - mQueryTextView.setImeOptions(imeOptions); - } - - /** - * Returns the IME options set on the query text field. - * @return the ime options - * @see TextView#setImeOptions(int) - * - * @attr ref android.R.styleable#SearchView_imeOptions - */ - public int getImeOptions() { - return mQueryTextView.getImeOptions(); - } - - /** - * Sets the input type on the query text field. - * - * @see TextView#setInputType(int) - * @param inputType the input type to set on the query text field - * - * @attr ref android.R.styleable#SearchView_inputType - */ - public void setInputType(int inputType) { - mQueryTextView.setInputType(inputType); - } - - /** - * Returns the input type set on the query text field. - * @return the input type - * - * @attr ref android.R.styleable#SearchView_inputType - */ - public int getInputType() { - return mQueryTextView.getInputType(); - } - - /** @hide */ - @Override - public boolean requestFocus(int direction, Rect previouslyFocusedRect) { - // Don't accept focus if in the middle of clearing focus - if (mClearingFocus) return false; - // Check if SearchView is focusable. - if (!isFocusable()) return false; - // If it is not iconified, then give the focus to the text field - if (!isIconified()) { - boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect); - if (result) { - updateViewsVisibility(false); - } - return result; - } else { - return super.requestFocus(direction, previouslyFocusedRect); - } - } - - /** @hide */ - @Override - public void clearFocus() { - mClearingFocus = true; - setImeVisibility(false); - super.clearFocus(); - mQueryTextView.clearFocus(); - mClearingFocus = false; - } - - /** - * Sets a listener for user actions within the SearchView. - * - * @param listener the listener object that receives callbacks when the user performs - * actions in the SearchView such as clicking on buttons or typing a query. - */ - public void setOnQueryTextListener(OnQueryTextListener listener) { - mOnQueryChangeListener = listener; - } - - /** - * Sets a listener to inform when the user closes the SearchView. - * - * @param listener the listener to call when the user closes the SearchView. - */ - public void setOnCloseListener(OnCloseListener listener) { - mOnCloseListener = listener; - } - - /** - * Sets a listener to inform when the focus of the query text field changes. - * - * @param listener the listener to inform of focus changes. - */ - public void setOnQueryTextFocusChangeListener(OnFocusChangeListener listener) { - mOnQueryTextFocusChangeListener = listener; - } - - /** - * Sets a listener to inform when a suggestion is focused or clicked. - * - * @param listener the listener to inform of suggestion selection events. - */ - public void setOnSuggestionListener(OnSuggestionListener listener) { - mOnSuggestionListener = listener; - } - - /** - * Sets a listener to inform when the search button is pressed. This is only - * relevant when the text field is not visible by default. Calling {@link #setIconified - * setIconified(false)} can also cause this listener to be informed. - * - * @param listener the listener to inform when the search button is clicked or - * the text field is programmatically de-iconified. - */ - public void setOnSearchClickListener(OnClickListener listener) { - mOnSearchClickListener = listener; - } - - /** - * Returns the query string currently in the text field. - * - * @return the query string - */ - public CharSequence getQuery() { - return mQueryTextView.getText(); - } - - /** - * Sets a query string in the text field and optionally submits the query as well. - * - * @param query the query string. This replaces any query text already present in the - * text field. - * @param submit whether to submit the query right now or only update the contents of - * text field. - */ - public void setQuery(CharSequence query, boolean submit) { - mQueryTextView.setText(query); - if (query != null) { - mQueryTextView.setSelection(mQueryTextView.length()); - mUserQuery = query; - } - - // If the query is not empty and submit is requested, submit the query - if (submit && !TextUtils.isEmpty(query)) { - onSubmitQuery(); - } - } - - /** - * Sets the hint text to display in the query text field. This overrides any hint specified - * in the SearchableInfo. - * - * @param hint the hint text to display - * - * @attr ref android.R.styleable#SearchView_queryHint - */ - public void setQueryHint(CharSequence hint) { - mQueryHint = hint; - updateQueryHint(); - } - - /** - * Gets the hint text to display in the query text field. - * @return the query hint text, if specified, null otherwise. - * - * @attr ref android.R.styleable#SearchView_queryHint - */ - public CharSequence getQueryHint() { - if (mQueryHint != null) { - return mQueryHint; - } else if (mSearchable != null) { - CharSequence hint = null; - int hintId = mSearchable.getHintId(); - if (hintId != 0) { - hint = getContext().getString(hintId); - } - return hint; - } - return null; - } - - /** - * Sets the default or resting state of the search field. If true, a single search icon is - * shown by default and expands to show the text field and other buttons when pressed. Also, - * if the default state is iconified, then it collapses to that state when the close button - * is pressed. Changes to this property will take effect immediately. - * - *

The default value is true.

- * - * @param iconified whether the search field should be iconified by default - * - * @attr ref android.R.styleable#SearchView_iconifiedByDefault - */ - public void setIconifiedByDefault(boolean iconified) { - if (mIconifiedByDefault == iconified) return; - mIconifiedByDefault = iconified; - updateViewsVisibility(iconified); - updateQueryHint(); - } - - /** - * Returns the default iconified state of the search field. - * @return - * - * @attr ref android.R.styleable#SearchView_iconifiedByDefault - */ - public boolean isIconfiedByDefault() { - return mIconifiedByDefault; - } - - /** - * Iconifies or expands the SearchView. Any query text is cleared when iconified. This is - * a temporary state and does not override the default iconified state set by - * {@link #setIconifiedByDefault(boolean)}. If the default state is iconified, then - * a false here will only be valid until the user closes the field. And if the default - * state is expanded, then a true here will only clear the text field and not close it. - * - * @param iconify a true value will collapse the SearchView to an icon, while a false will - * expand it. - */ - public void setIconified(boolean iconify) { - if (iconify) { - onCloseClicked(); - } else { - onSearchClicked(); - } - } - - /** - * Returns the current iconified state of the SearchView. - * - * @return true if the SearchView is currently iconified, false if the search field is - * fully visible. - */ - public boolean isIconified() { - return mIconified; - } - - /** - * Enables showing a submit button when the query is non-empty. In cases where the SearchView - * is being used to filter the contents of the current activity and doesn't launch a separate - * results activity, then the submit button should be disabled. - * - * @param enabled true to show a submit button for submitting queries, false if a submit - * button is not required. - */ - public void setSubmitButtonEnabled(boolean enabled) { - mSubmitButtonEnabled = enabled; - updateViewsVisibility(isIconified()); - } - - /** - * Returns whether the submit button is enabled when necessary or never displayed. - * - * @return whether the submit button is enabled automatically when necessary - */ - public boolean isSubmitButtonEnabled() { - return mSubmitButtonEnabled; - } - - /** - * Specifies if a query refinement button should be displayed alongside each suggestion - * or if it should depend on the flags set in the individual items retrieved from the - * suggestions provider. Clicking on the query refinement button will replace the text - * in the query text field with the text from the suggestion. This flag only takes effect - * if a SearchableInfo has been specified with {@link #setSearchableInfo(SearchableInfo)} - * and not when using a custom adapter. - * - * @param enable true if all items should have a query refinement button, false if only - * those items that have a query refinement flag set should have the button. - * - * @see SearchManager#SUGGEST_COLUMN_FLAGS - * @see SearchManager#FLAG_QUERY_REFINEMENT - */ - public void setQueryRefinementEnabled(boolean enable) { - mQueryRefinement = enable; - if (mSuggestionsAdapter instanceof SuggestionsAdapter) { - ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement( - enable ? SuggestionsAdapter.REFINE_ALL : SuggestionsAdapter.REFINE_BY_ENTRY); - } - } - - /** - * Returns whether query refinement is enabled for all items or only specific ones. - * @return true if enabled for all items, false otherwise. - */ - public boolean isQueryRefinementEnabled() { - return mQueryRefinement; - } - - /** - * You can set a custom adapter if you wish. Otherwise the default adapter is used to - * display the suggestions from the suggestions provider associated with the SearchableInfo. - * - * @see #setSearchableInfo(SearchableInfo) - */ - public void setSuggestionsAdapter(CursorAdapter adapter) { - mSuggestionsAdapter = adapter; - - mQueryTextView.setAdapter(mSuggestionsAdapter); - } - - /** - * Returns the adapter used for suggestions, if any. - * @return the suggestions adapter - */ - public CursorAdapter getSuggestionsAdapter() { - return mSuggestionsAdapter; - } - - /** - * Makes the view at most this many pixels wide - * - * @attr ref android.R.styleable#SearchView_maxWidth - */ - public void setMaxWidth(int maxpixels) { - mMaxWidth = maxpixels; - - requestLayout(); - } - - /** - * Gets the specified maximum width in pixels, if set. Returns zero if - * no maximum width was specified. - * @return the maximum width of the view - * - * @attr ref android.R.styleable#SearchView_maxWidth - */ - public int getMaxWidth() { - return mMaxWidth; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Let the standard measurements take effect in iconified state. - if (isIconified()) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - return; - } - - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int width = MeasureSpec.getSize(widthMeasureSpec); - - switch (widthMode) { - case MeasureSpec.AT_MOST: - // If there is an upper limit, don't exceed maximum width (explicit or implicit) - if (mMaxWidth > 0) { - width = Math.min(mMaxWidth, width); - } else { - width = Math.min(getPreferredWidth(), width); - } - break; - case MeasureSpec.EXACTLY: - // If an exact width is specified, still don't exceed any specified maximum width - if (mMaxWidth > 0) { - width = Math.min(mMaxWidth, width); - } - break; - case MeasureSpec.UNSPECIFIED: - // Use maximum width, if specified, else preferred width - width = mMaxWidth > 0 ? mMaxWidth : getPreferredWidth(); - break; - } - widthMode = MeasureSpec.EXACTLY; - super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); - } - - private int getPreferredWidth() { - return getContext().getResources() - .getDimensionPixelSize(R.dimen.abs__search_view_preferred_width); - } - - private void updateViewsVisibility(final boolean collapsed) { - mIconified = collapsed; - // Visibility of views that are visible when collapsed - final int visCollapsed = collapsed ? VISIBLE : GONE; - // Is there text in the query - final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); - - mSearchButton.setVisibility(visCollapsed); - updateSubmitButton(hasText); - mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); - mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE); - updateCloseButton(); - updateVoiceButton(!hasText); - updateSubmitArea(); - } - - private boolean hasVoiceSearch() { - if (mSearchable != null && mSearchable.getVoiceSearchEnabled()) { - Intent testIntent = null; - if (mSearchable.getVoiceSearchLaunchWebSearch()) { - testIntent = mVoiceWebSearchIntent; - } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { - testIntent = mVoiceAppSearchIntent; - } - if (testIntent != null) { - ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent, - PackageManager.MATCH_DEFAULT_ONLY); - return ri != null; - } - } - return false; - } - - private boolean isSubmitAreaEnabled() { - return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified(); - } - - private void updateSubmitButton(boolean hasText) { - int visibility = GONE; - if (mSubmitButtonEnabled && isSubmitAreaEnabled() && hasFocus() - && (hasText || !mVoiceButtonEnabled)) { - visibility = VISIBLE; - } - mSubmitButton.setVisibility(visibility); - } - - private void updateSubmitArea() { - int visibility = GONE; - if (isSubmitAreaEnabled() - && (mSubmitButton.getVisibility() == VISIBLE - || mVoiceButton.getVisibility() == VISIBLE)) { - visibility = VISIBLE; - } - mSubmitArea.setVisibility(visibility); - } - - private void updateCloseButton() { - final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); - // Should we show the close button? It is not shown if there's no focus, - // field is not iconified by default and there is no text in it. - final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView); - mCloseButton.setVisibility(showClose ? VISIBLE : GONE); - mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); - } - - private void postUpdateFocusedState() { - post(mUpdateDrawableStateRunnable); - } - - private void updateFocusedState() { - boolean focused = mQueryTextView.hasFocus(); - mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); - mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); - invalidate(); - } - - @Override - protected void onDetachedFromWindow() { - removeCallbacks(mUpdateDrawableStateRunnable); - post(mReleaseCursorRunnable); - super.onDetachedFromWindow(); - } - - private void setImeVisibility(final boolean visible) { - if (visible) { - post(mShowImeRunnable); - } else { - removeCallbacks(mShowImeRunnable); - InputMethodManager imm = (InputMethodManager) - getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - - if (imm != null) { - imm.hideSoftInputFromWindow(getWindowToken(), 0); - } - } - } - - /** - * Called by the SuggestionsAdapter - * @hide - */ - /* package */void onQueryRefine(CharSequence queryText) { - setQuery(queryText); - } - - private final OnClickListener mOnClickListener = new OnClickListener() { - - public void onClick(View v) { - if (v == mSearchButton) { - onSearchClicked(); - } else if (v == mCloseButton) { - onCloseClicked(); - } else if (v == mSubmitButton) { - onSubmitQuery(); - } else if (v == mVoiceButton) { - onVoiceClicked(); - } else if (v == mQueryTextView) { - forceSuggestionQuery(); - } - } - }; - - /** - * Handles the key down event for dealing with action keys. - * - * @param keyCode This is the keycode of the typed key, and is the same value as - * found in the KeyEvent parameter. - * @param event The complete event record for the typed key - * - * @return true if the event was handled here, or false if not. - */ - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (mSearchable == null) { - return false; - } - - // if it's an action specified by the searchable activity, launch the - // entered query with the action key - // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); - // TODO if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) { - // TODO launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView.getText() - // TODO .toString()); - // TODO return true; - // TODO } - - return super.onKeyDown(keyCode, event); - } - - /** - * React to the user typing "enter" or other hardwired keys while typing in - * the search box. This handles these special keys while the edit box has - * focus. - */ - View.OnKeyListener mTextKeyListener = new View.OnKeyListener() { - public boolean onKey(View v, int keyCode, KeyEvent event) { - // guard against possible race conditions - if (mSearchable == null) { - return false; - } - - if (DBG) { - Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event + "), selection: " - + mQueryTextView.getListSelection()); - } - - // If a suggestion is selected, handle enter, search key, and action keys - // as presses on the selected suggestion - if (mQueryTextView.isPopupShowing() - && mQueryTextView.getListSelection() != ListView.INVALID_POSITION) { - return onSuggestionsKey(v, keyCode, event); - } - - // If there is text in the query box, handle enter, and action keys - // The search key is handled by the dialog's onKeyDown(). - if (!mQueryTextView.isEmpty() && KeyEventCompat.hasNoModifiers(event)) { - if (event.getAction() == KeyEvent.ACTION_UP) { - if (keyCode == KeyEvent.KEYCODE_ENTER) { - v.cancelLongPress(); - - // Launch as a regular search. - launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText() - .toString()); - return true; - } - } - if (event.getAction() == KeyEvent.ACTION_DOWN) { - // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); - // TODO if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) { - // TODO launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView - // TODO .getText().toString()); - // TODO return true; - // TODO } - } - } - return false; - } - }; - - /** - * React to the user typing while in the suggestions list. First, check for - * action keys. If not handled, try refocusing regular characters into the - * EditText. - */ - private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) { - // guard against possible race conditions (late arrival after dismiss) - if (mSearchable == null) { - return false; - } - if (mSuggestionsAdapter == null) { - return false; - } - if (event.getAction() == KeyEvent.ACTION_DOWN && KeyEventCompat.hasNoModifiers(event)) { - // First, check for enter or search (both of which we'll treat as a - // "click") - if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH - || keyCode == KeyEvent.KEYCODE_TAB) { - int position = mQueryTextView.getListSelection(); - return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null); - } - - // Next, check for left/right moves, which we use to "return" the - // user to the edit view - if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { - // give "focus" to text editor, with cursor at the beginning if - // left key, at end if right key - // TODO: Reverse left/right for right-to-left languages, e.g. - // Arabic - int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView - .length(); - mQueryTextView.setSelection(selPoint); - mQueryTextView.setListSelection(0); - mQueryTextView.clearListSelection(); - ensureImeVisible(mQueryTextView, true); - - return true; - } - - // Next, check for an "up and out" move - if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection()) { - // TODO: restoreUserQuery(); - // let ACTV complete the move - return false; - } - - // Next, check for an "action key" - // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); - // TODO if ((actionKey != null) - // TODO && ((actionKey.getSuggestActionMsg() != null) || (actionKey - // TODO .getSuggestActionMsgColumn() != null))) { - // TODO // launch suggestion using action key column - // TODO int position = mQueryTextView.getListSelection(); - // TODO if (position != ListView.INVALID_POSITION) { - // TODO Cursor c = mSuggestionsAdapter.getCursor(); - // TODO if (c.moveToPosition(position)) { - // TODO final String actionMsg = getActionKeyMessage(c, actionKey); - // TODO if (actionMsg != null && (actionMsg.length() > 0)) { - // TODO return onItemClicked(position, keyCode, actionMsg); - // TODO } - // TODO } - // TODO } - // TODO } - } - return false; - } - - /** - * For a given suggestion and a given cursor row, get the action message. If - * not provided by the specific row/column, also check for a single - * definition (for the action key). - * - * @param c The cursor providing suggestions - * @param actionKey The actionkey record being examined - * - * @return Returns a string, or null if no action key message for this - * suggestion - */ - // TODO private static String getActionKeyMessage(Cursor c, SearchableInfo.ActionKeyInfo actionKey) { - // TODO String result = null; - // TODO // check first in the cursor data, for a suggestion-specific message - // TODO final String column = actionKey.getSuggestActionMsgColumn(); - // TODO if (column != null) { - // TODO result = SuggestionsAdapter.getColumnString(c, column); - // TODO } - // TODO // If the cursor didn't give us a message, see if there's a single - // TODO // message defined - // TODO // for the actionkey (for all suggestions) - // TODO if (result == null) { - // TODO result = actionKey.getSuggestActionMsg(); - // TODO } - // TODO return result; - // TODO } - - private int getSearchIconId() { - TypedValue outValue = new TypedValue(); - getContext().getTheme().resolveAttribute(R.attr.searchViewSearchIcon, - outValue, true); - return outValue.resourceId; - } - - private CharSequence getDecoratedHint(CharSequence hintText) { - // If the field is always expanded, then don't add the search icon to the hint - if (!mIconifiedByDefault) return hintText; - - SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon - ssb.append(hintText); - Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId()); - int textSize = (int) (mQueryTextView.getTextSize() * 1.25); - searchIcon.setBounds(0, 0, textSize, textSize); - ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - return ssb; - } - - private void updateQueryHint() { - if (mQueryHint != null) { - mQueryTextView.setHint(getDecoratedHint(mQueryHint)); - } else if (mSearchable != null) { - CharSequence hint = null; - int hintId = mSearchable.getHintId(); - if (hintId != 0) { - hint = getContext().getString(hintId); - } - if (hint != null) { - mQueryTextView.setHint(getDecoratedHint(hint)); - } - } else { - mQueryTextView.setHint(getDecoratedHint("")); - } - } - - /** - * Updates the auto-complete text view. - */ - private void updateSearchAutoComplete() { - // TODO mQueryTextView.setDropDownAnimationStyle(0); // no animation - mQueryTextView.setThreshold(mSearchable.getSuggestThreshold()); - mQueryTextView.setImeOptions(mSearchable.getImeOptions()); - int inputType = mSearchable.getInputType(); - // We only touch this if the input type is set up for text (which it almost certainly - // should be, in the case of search!) - if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { - // The existence of a suggestions authority is the proxy for "suggestions - // are available here" - inputType &= ~InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; - if (mSearchable.getSuggestAuthority() != null) { - inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; - // TYPE_TEXT_FLAG_AUTO_COMPLETE means that the text editor is performing - // auto-completion based on its own semantics, which it will present to the user - // as they type. This generally means that the input method should not show its - // own candidates, and the spell checker should not be in action. The text editor - // supplies its candidates by calling InputMethodManager.displayCompletions(), - // which in turn will call InputMethodSession.displayCompletions(). - inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; - } - } - mQueryTextView.setInputType(inputType); - if (mSuggestionsAdapter != null) { - mSuggestionsAdapter.changeCursor(null); - } - // attach the suggestions adapter, if suggestions are available - // The existence of a suggestions authority is the proxy for "suggestions available here" - if (mSearchable.getSuggestAuthority() != null) { - mSuggestionsAdapter = new SuggestionsAdapter(getContext(), - this, mSearchable, mOutsideDrawablesCache); - mQueryTextView.setAdapter(mSuggestionsAdapter); - ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement( - mQueryRefinement ? SuggestionsAdapter.REFINE_ALL - : SuggestionsAdapter.REFINE_BY_ENTRY); - } - } - - /** - * Update the visibility of the voice button. There are actually two voice search modes, - * either of which will activate the button. - * @param empty whether the search query text field is empty. If it is, then the other - * criteria apply to make the voice button visible. - */ - private void updateVoiceButton(boolean empty) { - int visibility = GONE; - if (mVoiceButtonEnabled && !isIconified() && empty) { - visibility = VISIBLE; - mSubmitButton.setVisibility(GONE); - } - mVoiceButton.setVisibility(visibility); - } - - private final OnEditorActionListener mOnEditorActionListener = new OnEditorActionListener() { - - /** - * Called when the input method default action key is pressed. - */ - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - onSubmitQuery(); - return true; - } - }; - - private void onTextChanged(CharSequence newText) { - CharSequence text = mQueryTextView.getText(); - mUserQuery = text; - boolean hasText = !TextUtils.isEmpty(text); - updateSubmitButton(hasText); - updateVoiceButton(!hasText); - updateCloseButton(); - updateSubmitArea(); - if (mOnQueryChangeListener != null && !TextUtils.equals(newText, mOldQueryText)) { - mOnQueryChangeListener.onQueryTextChange(newText.toString()); - } - mOldQueryText = newText.toString(); - } - - private void onSubmitQuery() { - CharSequence query = mQueryTextView.getText(); - if (query != null && TextUtils.getTrimmedLength(query) > 0) { - if (mOnQueryChangeListener == null - || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) { - if (mSearchable != null) { - launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString()); - setImeVisibility(false); - } - dismissSuggestions(); - } - } - } - - private void dismissSuggestions() { - mQueryTextView.dismissDropDown(); - } - - private void onCloseClicked() { - CharSequence text = mQueryTextView.getText(); - if (TextUtils.isEmpty(text)) { - if (mIconifiedByDefault) { - // If the app doesn't override the close behavior - if (mOnCloseListener == null || !mOnCloseListener.onClose()) { - // hide the keyboard and remove focus - clearFocus(); - // collapse the search field - updateViewsVisibility(true); - } - } - } else { - mQueryTextView.setText(""); - mQueryTextView.requestFocus(); - setImeVisibility(true); - } - - } - - private void onSearchClicked() { - updateViewsVisibility(false); - mQueryTextView.requestFocus(); - setImeVisibility(true); - if (mOnSearchClickListener != null) { - mOnSearchClickListener.onClick(this); - } - } - - private void onVoiceClicked() { - // guard against possible race conditions - if (mSearchable == null) { - return; - } - SearchableInfo searchable = mSearchable; - try { - if (searchable.getVoiceSearchLaunchWebSearch()) { - Intent webSearchIntent = createVoiceWebSearchIntent(mVoiceWebSearchIntent, - searchable); - getContext().startActivity(webSearchIntent); - } else if (searchable.getVoiceSearchLaunchRecognizer()) { - Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent, - searchable); - getContext().startActivity(appSearchIntent); - } - } catch (ActivityNotFoundException e) { - // Should not happen, since we check the availability of - // voice search before showing the button. But just in case... - Log.w(LOG_TAG, "Could not find voice search activity"); - } - } - - void onTextFocusChanged() { - updateViewsVisibility(isIconified()); - // Delayed update to make sure that the focus has settled down and window focus changes - // don't affect it. A synchronous update was not working. - postUpdateFocusedState(); - if (mQueryTextView.hasFocus()) { - forceSuggestionQuery(); - } - } - - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - super.onWindowFocusChanged(hasWindowFocus); - - postUpdateFocusedState(); - } - - /** - * {@inheritDoc} - */ - @Override - public void onActionViewCollapsed() { - clearFocus(); - updateViewsVisibility(true); - mQueryTextView.setImeOptions(mCollapsedImeOptions); - mExpandedInActionView = false; - } - - /** - * {@inheritDoc} - */ - @Override - public void onActionViewExpanded() { - if (mExpandedInActionView) return; - - mExpandedInActionView = true; - mCollapsedImeOptions = mQueryTextView.getImeOptions(); - mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN); - mQueryTextView.setText(""); - setIconified(false); - } - - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setClassName(SearchView.class.getName()); - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setClassName(SearchView.class.getName()); - } - - private void adjustDropDownSizeAndPosition() { - if (mDropDownAnchor.getWidth() > 1) { - Resources res = getContext().getResources(); - int anchorPadding = mSearchPlate.getPaddingLeft(); - Rect dropDownPadding = new Rect(); - int iconOffset = mIconifiedByDefault - ? res.getDimensionPixelSize(R.dimen.abs__dropdownitem_icon_width) - + res.getDimensionPixelSize(R.dimen.abs__dropdownitem_text_padding_left) - : 0; - mQueryTextView.getDropDownBackground().getPadding(dropDownPadding); - mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset) - + anchorPadding); - mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left - + dropDownPadding.right + iconOffset - (anchorPadding)); - } - } - - private boolean onItemClicked(int position, int actionKey, String actionMsg) { - if (mOnSuggestionListener == null - || !mOnSuggestionListener.onSuggestionClick(position)) { - launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null); - setImeVisibility(false); - dismissSuggestions(); - return true; - } - return false; - } - - private boolean onItemSelected(int position) { - if (mOnSuggestionListener == null - || !mOnSuggestionListener.onSuggestionSelect(position)) { - rewriteQueryFromSuggestion(position); - return true; - } - return false; - } - - private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() { - - /** - * Implements OnItemClickListener - */ - public void onItemClick(AdapterView parent, View view, int position, long id) { - if (DBG) Log.d(LOG_TAG, "onItemClick() position " + position); - onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null); - } - }; - - private final OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() { - - /** - * Implements OnItemSelectedListener - */ - public void onItemSelected(AdapterView parent, View view, int position, long id) { - if (DBG) Log.d(LOG_TAG, "onItemSelected() position " + position); - SearchView.this.onItemSelected(position); - } - - /** - * Implements OnItemSelectedListener - */ - public void onNothingSelected(AdapterView parent) { - if (DBG) - Log.d(LOG_TAG, "onNothingSelected()"); - } - }; - - /** - * Query rewriting. - */ - private void rewriteQueryFromSuggestion(int position) { - CharSequence oldQuery = mQueryTextView.getText(); - Cursor c = mSuggestionsAdapter.getCursor(); - if (c == null) { - return; - } - if (c.moveToPosition(position)) { - // Get the new query from the suggestion. - CharSequence newQuery = mSuggestionsAdapter.convertToString(c); - if (newQuery != null) { - // The suggestion rewrites the query. - // Update the text field, without getting new suggestions. - setQuery(newQuery); - } else { - // The suggestion does not rewrite the query, restore the user's query. - setQuery(oldQuery); - } - } else { - // We got a bad position, restore the user's query. - setQuery(oldQuery); - } - } - - /** - * Launches an intent based on a suggestion. - * - * @param position The index of the suggestion to create the intent from. - * @param actionKey The key code of the action key that was pressed, - * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. - * @param actionMsg The message for the action key that was pressed, - * or null if none. - * @return true if a successful launch, false if could not (e.g. bad position). - */ - private boolean launchSuggestion(int position, int actionKey, String actionMsg) { - Cursor c = mSuggestionsAdapter.getCursor(); - if ((c != null) && c.moveToPosition(position)) { - - Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg); - - // launch the intent - launchIntent(intent); - - return true; - } - return false; - } - - /** - * Launches an intent, including any special intent handling. - */ - private void launchIntent(Intent intent) { - if (intent == null) { - return; - } - try { - // If the intent was created from a suggestion, it will always have an explicit - // component here. - getContext().startActivity(intent); - } catch (RuntimeException ex) { - Log.e(LOG_TAG, "Failed launch activity: " + intent, ex); - } - } - - /** - * Sets the text in the query box, without updating the suggestions. - */ - private void setQuery(CharSequence query) { - setText(mQueryTextView, query, true); - // Move the cursor to the end - mQueryTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length()); - } - - private void launchQuerySearch(int actionKey, String actionMsg, String query) { - String action = Intent.ACTION_SEARCH; - Intent intent = createIntent(action, null, null, query, actionKey, actionMsg); - getContext().startActivity(intent); - } - - /** - * Constructs an intent from the given information and the search dialog state. - * - * @param action Intent action. - * @param data Intent data, or null. - * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or null. - * @param query Intent query, or null. - * @param actionKey The key code of the action key that was pressed, - * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. - * @param actionMsg The message for the action key that was pressed, - * or null if none. - * @return The intent. - */ - private Intent createIntent(String action, Uri data, String extraData, String query, - int actionKey, String actionMsg) { - // Now build the Intent - Intent intent = new Intent(action); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - // We need CLEAR_TOP to avoid reusing an old task that has other activities - // on top of the one we want. We don't want to do this in in-app search though, - // as it can be destructive to the activity stack. - if (data != null) { - intent.setData(data); - } - intent.putExtra(SearchManager.USER_QUERY, mUserQuery); - if (query != null) { - intent.putExtra(SearchManager.QUERY, query); - } - if (extraData != null) { - intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); - } - if (mAppSearchData != null) { - intent.putExtra(SearchManager.APP_DATA, mAppSearchData); - } - if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { - intent.putExtra(SearchManager.ACTION_KEY, actionKey); - intent.putExtra(SearchManager.ACTION_MSG, actionMsg); - } - intent.setComponent(mSearchable.getSearchActivity()); - return intent; - } - - /** - * Create and return an Intent that can launch the voice search activity for web search. - */ - private Intent createVoiceWebSearchIntent(Intent baseIntent, SearchableInfo searchable) { - Intent voiceIntent = new Intent(baseIntent); - ComponentName searchActivity = searchable.getSearchActivity(); - voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null - : searchActivity.flattenToShortString()); - return voiceIntent; - } - - /** - * Create and return an Intent that can launch the voice search activity, perform a specific - * voice transcription, and forward the results to the searchable activity. - * - * @param baseIntent The voice app search intent to start from - * @return A completely-configured intent ready to send to the voice search activity - */ - private Intent createVoiceAppSearchIntent(Intent baseIntent, SearchableInfo searchable) { - ComponentName searchActivity = searchable.getSearchActivity(); - - // create the necessary intent to set up a search-and-forward operation - // in the voice search system. We have to keep the bundle separate, - // because it becomes immutable once it enters the PendingIntent - Intent queryIntent = new Intent(Intent.ACTION_SEARCH); - queryIntent.setComponent(searchActivity); - PendingIntent pending = PendingIntent.getActivity(getContext(), 0, queryIntent, - PendingIntent.FLAG_ONE_SHOT); - - // Now set up the bundle that will be inserted into the pending intent - // when it's time to do the search. We always build it here (even if empty) - // because the voice search activity will always need to insert "QUERY" into - // it anyway. - Bundle queryExtras = new Bundle(); - - // Now build the intent to launch the voice search. Add all necessary - // extras to launch the voice recognizer, and then all the necessary extras - // to forward the results to the searchable activity - Intent voiceIntent = new Intent(baseIntent); - - // Add all of the configuration options supplied by the searchable's metadata - String languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM; - String prompt = null; - String language = null; - int maxResults = 1; - - Resources resources = getResources(); - if (searchable.getVoiceLanguageModeId() != 0) { - languageModel = resources.getString(searchable.getVoiceLanguageModeId()); - } - if (searchable.getVoicePromptTextId() != 0) { - prompt = resources.getString(searchable.getVoicePromptTextId()); - } - if (searchable.getVoiceLanguageId() != 0) { - language = resources.getString(searchable.getVoiceLanguageId()); - } - if (searchable.getVoiceMaxResults() != 0) { - maxResults = searchable.getVoiceMaxResults(); - } - voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel); - voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); - voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); - voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults); - voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null - : searchActivity.flattenToShortString()); - - // Add the values that configure forwarding the results - voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending); - voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras); - - return voiceIntent; - } - - /** - * When a particular suggestion has been selected, perform the various lookups required - * to use the suggestion. This includes checking the cursor for suggestion-specific data, - * and/or falling back to the XML for defaults; It also creates REST style Uri data when - * the suggestion includes a data id. - * - * @param c The suggestions cursor, moved to the row of the user's selection - * @param actionKey The key code of the action key that was pressed, - * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. - * @param actionMsg The message for the action key that was pressed, - * or null if none. - * @return An intent for the suggestion at the cursor's position. - */ - private Intent createIntentFromSuggestion(Cursor c, int actionKey, String actionMsg) { - try { - // use specific action if supplied, or default action if supplied, or fixed default - String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION); - - if (action == null) { - action = mSearchable.getSuggestIntentAction(); - } - if (action == null) { - action = Intent.ACTION_SEARCH; - } - - // use specific data if supplied, or default data if supplied - String data = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA); - if (data == null) { - data = mSearchable.getSuggestIntentData(); - } - // then, if an ID was provided, append it. - if (data != null) { - String id = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); - if (id != null) { - data = data + "/" + Uri.encode(id); - } - } - Uri dataUri = (data == null) ? null : Uri.parse(data); - - String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY); - String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); - - return createIntent(action, dataUri, extraData, query, actionKey, actionMsg); - } catch (RuntimeException e ) { - int rowNum; - try { // be really paranoid now - rowNum = c.getPosition(); - } catch (RuntimeException e2 ) { - rowNum = -1; - } - Log.w(LOG_TAG, "Search suggestions cursor at row " + rowNum + - " returned exception.", e); - return null; - } - } - - private void forceSuggestionQuery() { - try { - Method before = SearchAutoComplete.class.getMethod("doBeforeTextChanged"); - Method after = SearchAutoComplete.class.getMethod("doAfterTextChanged"); - before.setAccessible(true); - after.setAccessible(true); - before.invoke(mQueryTextView); - after.invoke(mQueryTextView); - } catch (Exception e) { - // Oh well... - } - } - - static boolean isLandscapeMode(Context context) { - return context.getResources().getConfiguration().orientation - == Configuration.ORIENTATION_LANDSCAPE; - } - - /** - * Callback to watch the text field for empty/non-empty - */ - private TextWatcher mTextWatcher = new TextWatcher() { - - public void beforeTextChanged(CharSequence s, int start, int before, int after) { } - - public void onTextChanged(CharSequence s, int start, - int before, int after) { - SearchView.this.onTextChanged(s); - } - - public void afterTextChanged(Editable s) { - } - }; - - /** - * Local subclass for AutoCompleteTextView. - * @hide - */ - public static class SearchAutoComplete extends AutoCompleteTextView { - - private int mThreshold; - private SearchView mSearchView; - - public SearchAutoComplete(Context context) { - super(context); - mThreshold = getThreshold(); - } - - public SearchAutoComplete(Context context, AttributeSet attrs) { - super(context, attrs); - mThreshold = getThreshold(); - } - - public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mThreshold = getThreshold(); - } - - void setSearchView(SearchView searchView) { - mSearchView = searchView; - } - - @Override - public void setThreshold(int threshold) { - super.setThreshold(threshold); - mThreshold = threshold; - } - - /** - * Returns true if the text field is empty, or contains only whitespace. - */ - private boolean isEmpty() { - return TextUtils.getTrimmedLength(getText()) == 0; - } - - /** - * We override this method to avoid replacing the query box text when a - * suggestion is clicked. - */ - @Override - protected void replaceText(CharSequence text) { - } - - /** - * We override this method to avoid an extra onItemClick being called on - * the drop-down's OnItemClickListener by - * {@link AutoCompleteTextView#onKeyUp(int, KeyEvent)} when an item is - * clicked with the trackball. - */ - @Override - public void performCompletion() { - } - - /** - * We override this method to be sure and show the soft keyboard if - * appropriate when the TextView has focus. - */ - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - super.onWindowFocusChanged(hasWindowFocus); - - if (hasWindowFocus && mSearchView.hasFocus() && getVisibility() == VISIBLE) { - InputMethodManager inputManager = (InputMethodManager) getContext() - .getSystemService(Context.INPUT_METHOD_SERVICE); - inputManager.showSoftInput(this, 0); - // If in landscape mode, then make sure that - // the ime is in front of the dropdown. - if (isLandscapeMode(getContext())) { - ensureImeVisible(this, true); - } - } - } - - @Override - protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { - super.onFocusChanged(focused, direction, previouslyFocusedRect); - mSearchView.onTextFocusChanged(); - } - - /** - * We override this method so that we can allow a threshold of zero, - * which ACTV does not. - */ - @Override - public boolean enoughToFilter() { - return mThreshold <= 0 || super.enoughToFilter(); - } - - @Override - public boolean onKeyPreIme(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - // special case for the back key, we do not even try to send it - // to the drop down list but instead, consume it immediately - if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - KeyEvent.DispatcherState state = getKeyDispatcherState(); - if (state != null) { - state.startTracking(event, this); - } - return true; - } else if (event.getAction() == KeyEvent.ACTION_UP) { - KeyEvent.DispatcherState state = getKeyDispatcherState(); - if (state != null) { - state.handleUpEvent(event); - } - if (event.isTracking() && !event.isCanceled()) { - mSearchView.clearFocus(); - mSearchView.setImeVisibility(false); - return true; - } - } - } - return super.onKeyPreIme(keyCode, event); - } - - } - - private static void ensureImeVisible(AutoCompleteTextView view, boolean visible) { - try { - Method method = AutoCompleteTextView.class.getMethod("ensureImeVisible", boolean.class); - method.setAccessible(true); - method.invoke(view, visible); - } catch (Exception e) { - //Oh well... - } - } - - private static void showSoftInputUnchecked(View view, InputMethodManager imm, int flags) { - try { - Method method = imm.getClass().getMethod("showSoftInputUnchecked", int.class, ResultReceiver.class); - method.setAccessible(true); - method.invoke(imm, flags, null); - } catch (Exception e) { - //Fallback to public API which hopefully does mostly the same thing - imm.showSoftInput(view, flags); - } - } - - private static void setText(AutoCompleteTextView view, CharSequence text, boolean filter) { - try { - Method method = AutoCompleteTextView.class.getMethod("setText", CharSequence.class, boolean.class); - method.setAccessible(true); - method.invoke(view, text, filter); - } catch (Exception e) { - //Fallback to public API which hopefully does mostly the same thing - view.setText(text); - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java deleted file mode 100644 index 83e9f0ca9..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.widget; - -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Drawable; -import android.util.TypedValue; -import android.view.View; - -import com.actionbarsherlock.R; -import com.actionbarsherlock.view.ActionProvider; -import com.actionbarsherlock.view.Menu; -import com.actionbarsherlock.view.MenuItem; -import com.actionbarsherlock.view.MenuItem.OnMenuItemClickListener; -import com.actionbarsherlock.view.SubMenu; -import com.actionbarsherlock.widget.ActivityChooserModel.OnChooseActivityListener; - -/** - * This is a provider for a share action. It is responsible for creating views - * that enable data sharing and also to show a sub menu with sharing activities - * if the hosting item is placed on the overflow menu. - *

- * Here is how to use the action provider with custom backing file in a {@link MenuItem}: - *

- *

- *

- * 
- *  // In Activity#onCreateOptionsMenu
- *  public boolean onCreateOptionsMenu(Menu menu) {
- *      // Get the menu item.
- *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
- *      // Get the provider and hold onto it to set/change the share intent.
- *      mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
- *      // Set history different from the default before getting the action
- *      // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
- *      // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
- *      // line if using the default share history file is desired.
- *      mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
- *      . . .
- *  }
- *
- *  // Somewhere in the application.
- *  public void doShare(Intent shareIntent) {
- *      // When you want to share set the share intent.
- *      mShareActionProvider.setShareIntent(shareIntent);
- *  }
- * 
- * - *

- *

- * Note: While the sample snippet demonstrates how to use this provider - * in the context of a menu item, the use of the provider is not limited to menu items. - *

- * - * @see ActionProvider - */ -public class ShareActionProvider extends ActionProvider { - - /** - * Listener for the event of selecting a share target. - */ - public interface OnShareTargetSelectedListener { - - /** - * Called when a share target has been selected. The client can - * decide whether to handle the intent or rely on the default - * behavior which is launching it. - *

- * Note: Modifying the intent is not permitted and - * any changes to the latter will be ignored. - *

- * - * @param source The source of the notification. - * @param intent The intent for launching the chosen share target. - * @return Whether the client has handled the intent. - */ - public boolean onShareTargetSelected(ShareActionProvider source, Intent intent); - } - - /** - * The default for the maximal number of activities shown in the sub-menu. - */ - private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4; - - /** - * The the maximum number activities shown in the sub-menu. - */ - private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT; - - /** - * Listener for handling menu item clicks. - */ - private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener = - new ShareMenuItemOnMenuItemClickListener(); - - /** - * The default name for storing share history. - */ - public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml"; - - /** - * Context for accessing resources. - */ - private final Context mContext; - - /** - * The name of the file with share history data. - */ - private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME; - - private OnShareTargetSelectedListener mOnShareTargetSelectedListener; - - private OnChooseActivityListener mOnChooseActivityListener; - - /** - * Creates a new instance. - * - * @param context Context for accessing resources. - */ - public ShareActionProvider(Context context) { - super(context); - mContext = context; - } - - /** - * Sets a listener to be notified when a share target has been selected. - * The listener can optionally decide to handle the selection and - * not rely on the default behavior which is to launch the activity. - *

- * Note: If you choose the backing share history file - * you will still be notified in this callback. - *

- * @param listener The listener. - */ - public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) { - mOnShareTargetSelectedListener = listener; - setActivityChooserPolicyIfNeeded(); - } - - /** - * {@inheritDoc} - */ - @Override - public View onCreateActionView() { - // Create the view and set its data model. - ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); - ActivityChooserView activityChooserView = new ActivityChooserView(mContext); - activityChooserView.setActivityChooserModel(dataModel); - - // Lookup and set the expand action icon. - TypedValue outTypedValue = new TypedValue(); - mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true); - Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId); - activityChooserView.setExpandActivityOverflowButtonDrawable(drawable); - activityChooserView.setProvider(this); - - // Set content description. - activityChooserView.setDefaultActionButtonContentDescription( - R.string.abs__shareactionprovider_share_with_application); - activityChooserView.setExpandActivityOverflowButtonContentDescription( - R.string.abs__shareactionprovider_share_with); - - return activityChooserView; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasSubMenu() { - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public void onPrepareSubMenu(SubMenu subMenu) { - // Clear since the order of items may change. - subMenu.clear(); - - ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); - PackageManager packageManager = mContext.getPackageManager(); - - final int expandedActivityCount = dataModel.getActivityCount(); - final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount); - - // Populate the sub-menu with a sub set of the activities. - for (int i = 0; i < collapsedActivityCount; i++) { - ResolveInfo activity = dataModel.getActivity(i); - subMenu.add(0, i, i, activity.loadLabel(packageManager)) - .setIcon(activity.loadIcon(packageManager)) - .setOnMenuItemClickListener(mOnMenuItemClickListener); - } - - if (collapsedActivityCount < expandedActivityCount) { - // Add a sub-menu for showing all activities as a list item. - SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount, - collapsedActivityCount, - mContext.getString(R.string.abs__activity_chooser_view_see_all)); - for (int i = 0; i < expandedActivityCount; i++) { - ResolveInfo activity = dataModel.getActivity(i); - expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager)) - .setIcon(activity.loadIcon(packageManager)) - .setOnMenuItemClickListener(mOnMenuItemClickListener); - } - } - } - - /** - * Sets the file name of a file for persisting the share history which - * history will be used for ordering share targets. This file will be used - * for all view created by {@link #onCreateActionView()}. Defaults to - * {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to null - * if share history should not be persisted between sessions. - *

- * Note: The history file name can be set any time, however - * only the action views created by {@link #onCreateActionView()} after setting - * the file name will be backed by the provided file. - *

- * - * @param shareHistoryFile The share history file name. - */ - public void setShareHistoryFileName(String shareHistoryFile) { - mShareHistoryFileName = shareHistoryFile; - setActivityChooserPolicyIfNeeded(); - } - - /** - * Sets an intent with information about the share action. Here is a - * sample for constructing a share intent: - *

- *

-     * 
-     *  Intent shareIntent = new Intent(Intent.ACTION_SEND);
-     *  shareIntent.setType("image/*");
-     *  Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
-     *  shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
-     * 
- * - *

- * - * @param shareIntent The share intent. - * - * @see Intent#ACTION_SEND - * @see Intent#ACTION_SEND_MULTIPLE - */ - public void setShareIntent(Intent shareIntent) { - ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, - mShareHistoryFileName); - dataModel.setIntent(shareIntent); - } - - /** - * Reusable listener for handling share item clicks. - */ - private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener { - @Override - public boolean onMenuItemClick(MenuItem item) { - ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, - mShareHistoryFileName); - final int itemId = item.getItemId(); - Intent launchIntent = dataModel.chooseActivity(itemId); - if (launchIntent != null) { - mContext.startActivity(launchIntent); - } - return true; - } - } - - /** - * Set the activity chooser policy of the model backed by the current - * share history file if needed which is if there is a registered callback. - */ - private void setActivityChooserPolicyIfNeeded() { - if (mOnShareTargetSelectedListener == null) { - return; - } - if (mOnChooseActivityListener == null) { - mOnChooseActivityListener = new ShareAcitivityChooserModelPolicy(); - } - ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); - dataModel.setOnChooseActivityListener(mOnChooseActivityListener); - } - - /** - * Policy that delegates to the {@link OnShareTargetSelectedListener}, if such. - */ - private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener { - @Override - public boolean onChooseActivity(ActivityChooserModel host, Intent intent) { - if (mOnShareTargetSelectedListener != null) { - return mOnShareTargetSelectedListener.onShareTargetSelected( - ShareActionProvider.this, intent); - } - return false; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java deleted file mode 100644 index bd5cbd718..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.actionbarsherlock.widget; - -import android.app.SearchManager; -import android.app.SearchableInfo; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.database.Cursor; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.widget.ResourceCursorAdapter; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.TextUtils; -import android.text.style.TextAppearanceSpan; -import android.util.Log; -import android.util.TypedValue; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; -import com.actionbarsherlock.R; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.WeakHashMap; - -/** - * Provides the contents for the suggestion drop-down list. - * - * @hide - */ -class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListener { - - private static final boolean DBG = false; - private static final String LOG_TAG = "SuggestionsAdapter"; - private static final int QUERY_LIMIT = 50; - - static final int REFINE_NONE = 0; - static final int REFINE_BY_ENTRY = 1; - static final int REFINE_ALL = 2; - - private SearchManager mSearchManager; - private SearchView mSearchView; - private Context mProviderContext; - private WeakHashMap mOutsideDrawablesCache; - private boolean mClosed = false; - private int mQueryRefinement = REFINE_BY_ENTRY; - - // URL color - private ColorStateList mUrlColor; - - static final int INVALID_INDEX = -1; - - // Cached column indexes, updated when the cursor changes. - private int mText1Col = INVALID_INDEX; - private int mText2Col = INVALID_INDEX; - private int mText2UrlCol = INVALID_INDEX; - private int mIconName1Col = INVALID_INDEX; - private int mIconName2Col = INVALID_INDEX; - private int mFlagsCol = INVALID_INDEX; - - // private final Runnable mStartSpinnerRunnable; - // private final Runnable mStopSpinnerRunnable; - - /** - * The amount of time we delay in the filter when the user presses the delete key. - */ - //private static final long DELETE_KEY_POST_DELAY = 500L; - - public SuggestionsAdapter(Context context, SearchView searchView, - SearchableInfo mSearchable, WeakHashMap outsideDrawablesCache) { - super(context, - R.layout.abs__search_dropdown_item_icons_2line, - null, // no initial cursor - true); // auto-requery - mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); - mProviderContext = mContext; - mSearchView = searchView; - - mOutsideDrawablesCache = outsideDrawablesCache; - - // mStartSpinnerRunnable = new Runnable() { - // public void run() { - // // mSearchView.setWorking(true); // TODO: - // } - // }; - // - // mStopSpinnerRunnable = new Runnable() { - // public void run() { - // // mSearchView.setWorking(false); // TODO: - // } - // }; - - // delay 500ms when deleting -// TODO getFilter().setDelayer(new Filter.Delayer() { -// -// private int mPreviousLength = 0; -// -// public long getPostingDelay(CharSequence constraint) { -// if (constraint == null) return 0; -// -// long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0; -// mPreviousLength = constraint.length(); -// return delay; -// } -// }); - } - - /** - * Enables query refinement for all suggestions. This means that an additional icon - * will be shown for each entry. When clicked, the suggested text on that line will be - * copied to the query text field. - *

- * - * @param refineWhat which queries to refine. Possible values are {@link #REFINE_NONE}, - * {@link #REFINE_BY_ENTRY}, and {@link #REFINE_ALL}. - */ - public void setQueryRefinement(int refineWhat) { - mQueryRefinement = refineWhat; - } - - /** - * Returns the current query refinement preference. - * @return value of query refinement preference - */ - public int getQueryRefinement() { - return mQueryRefinement; - } - - /** - * Overridden to always return false, since we cannot be sure that - * suggestion sources return stable IDs. - */ - @Override - public boolean hasStableIds() { - return false; - } - - /** - * Use the search suggestions provider to obtain a live cursor. This will be called - * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions). - * The results will be processed in the UI thread and changeCursor() will be called. - */ - @Override - public Cursor runQueryOnBackgroundThread(CharSequence constraint) { - if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")"); - String query = (constraint == null) ? "" : constraint.toString(); - /** - * for in app search we show the progress spinner until the cursor is returned with - * the results. - */ - Cursor cursor = null; - if (mSearchView.getVisibility() != View.VISIBLE - || mSearchView.getWindowVisibility() != View.VISIBLE) { - return null; - } - //mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO: - try { - cursor = getSuggestions(query, QUERY_LIMIT); - // trigger fill window so the spinner stays up until the results are copied over and - // closer to being ready - if (cursor != null) { - cursor.getCount(); - return cursor; - } - } catch (RuntimeException e) { - Log.w(LOG_TAG, "Search suggestions query threw an exception.", e); - } - // If cursor is null or an exception was thrown, stop the spinner and return null. - // changeCursor doesn't get called if cursor is null - // mSearchView.getWindow().getDecorView().post(mStopSpinnerRunnable); // TODO: - return null; - } - - public Cursor getSuggestions(String query, int limit) { - Uri.Builder uriBuilder = new Uri.Builder() - .scheme(ContentResolver.SCHEME_CONTENT) - .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() - .fragment(""); // TODO: Remove, workaround for a bug in Uri.writeToParcel() - - // append standard suggestion query path - uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); - - // inject query, either as selection args or inline - uriBuilder.appendPath(query); - - if (limit > 0) { - uriBuilder.appendQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT, String.valueOf(limit)); - } - - Uri uri = uriBuilder.build(); - - // finally, make the query - return mContext.getContentResolver().query(uri, null, null, null, null); - } - - public void close() { - if (DBG) Log.d(LOG_TAG, "close()"); - changeCursor(null); - mClosed = true; - } - - @Override - public void notifyDataSetChanged() { - if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged"); - super.notifyDataSetChanged(); - - // mSearchView.onDataSetChanged(); // TODO: - - updateSpinnerState(getCursor()); - } - - @Override - public void notifyDataSetInvalidated() { - if (DBG) Log.d(LOG_TAG, "notifyDataSetInvalidated"); - super.notifyDataSetInvalidated(); - - updateSpinnerState(getCursor()); - } - - private void updateSpinnerState(Cursor cursor) { - Bundle extras = cursor != null ? cursor.getExtras() : null; - if (DBG) { - Log.d(LOG_TAG, "updateSpinnerState - extra = " - + (extras != null - ? extras.getBoolean(SearchManager.CURSOR_EXTRA_KEY_IN_PROGRESS) - : null)); - } - // Check if the Cursor indicates that the query is not complete and show the spinner - if (extras != null - && extras.getBoolean(SearchManager.CURSOR_EXTRA_KEY_IN_PROGRESS)) { - // mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO: - return; - } - // If cursor is null or is done, stop the spinner - // mSearchView.getWindow().getDecorView().post(mStopSpinnerRunnable); // TODO: - } - - /** - * Cache columns. - */ - @Override - public void changeCursor(Cursor c) { - if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")"); - - if (mClosed) { - Log.w(LOG_TAG, "Tried to change cursor after adapter was closed."); - if (c != null) c.close(); - return; - } - - try { - super.changeCursor(c); - - if (c != null) { - mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1); - mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2); - mText2UrlCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL); - mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1); - mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2); - mFlagsCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FLAGS); - } - } catch (Exception e) { - Log.e(LOG_TAG, "error changing cursor and caching columns", e); - } - } - - /** - * Tags the view with cached child view look-ups. - */ - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - View v = super.newView(context, cursor, parent); - v.setTag(new ChildViewCache(v)); - return v; - } - - /** - * Cache of the child views of drop-drown list items, to avoid looking up the children - * each time the contents of a list item are changed. - */ - private final static class ChildViewCache { - public final TextView mText1; - public final TextView mText2; - public final ImageView mIcon1; - public final ImageView mIcon2; - public final ImageView mIconRefine; - - public ChildViewCache(View v) { - mText1 = (TextView) v.findViewById(android.R.id.text1); - mText2 = (TextView) v.findViewById(android.R.id.text2); - mIcon1 = (ImageView) v.findViewById(android.R.id.icon1); - mIcon2 = (ImageView) v.findViewById(android.R.id.icon2); - mIconRefine = (ImageView) v.findViewById(R.id.edit_query); - } - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - ChildViewCache views = (ChildViewCache) view.getTag(); - - int flags = 0; - if (mFlagsCol != INVALID_INDEX) { - flags = cursor.getInt(mFlagsCol); - } - if (views.mText1 != null) { - String text1 = getStringOrNull(cursor, mText1Col); - setViewText(views.mText1, text1); - } - if (views.mText2 != null) { - // First check TEXT_2_URL - CharSequence text2 = getStringOrNull(cursor, mText2UrlCol); - if (text2 != null) { - text2 = formatUrl(text2); - } else { - text2 = getStringOrNull(cursor, mText2Col); - } - - // If no second line of text is indicated, allow the first line of text - // to be up to two lines if it wants to be. - if (TextUtils.isEmpty(text2)) { - if (views.mText1 != null) { - views.mText1.setSingleLine(false); - views.mText1.setMaxLines(2); - } - } else { - if (views.mText1 != null) { - views.mText1.setSingleLine(true); - views.mText1.setMaxLines(1); - } - } - setViewText(views.mText2, text2); - } - - if (views.mIcon1 != null) { - setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE); - } - if (views.mIcon2 != null) { - setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE); - } - if (mQueryRefinement == REFINE_ALL - || (mQueryRefinement == REFINE_BY_ENTRY - && (flags & SearchManager.FLAG_QUERY_REFINEMENT) != 0)) { - views.mIconRefine.setVisibility(View.VISIBLE); - views.mIconRefine.setTag(views.mText1.getText()); - views.mIconRefine.setOnClickListener(this); - } else { - views.mIconRefine.setVisibility(View.GONE); - } - } - - public void onClick(View v) { - Object tag = v.getTag(); - if (tag instanceof CharSequence) { - mSearchView.onQueryRefine((CharSequence) tag); - } - } - - private CharSequence formatUrl(CharSequence url) { - if (mUrlColor == null) { - // Lazily get the URL color from the current theme. - TypedValue colorValue = new TypedValue(); - mContext.getTheme().resolveAttribute(R.attr.textColorSearchUrl, colorValue, true); - mUrlColor = mContext.getResources().getColorStateList(colorValue.resourceId); - } - - SpannableString text = new SpannableString(url); - text.setSpan(new TextAppearanceSpan(null, 0, 0, mUrlColor, null), - 0, url.length(), - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - return text; - } - - private void setViewText(TextView v, CharSequence text) { - // Set the text even if it's null, since we need to clear any previous text. - v.setText(text); - - if (TextUtils.isEmpty(text)) { - v.setVisibility(View.GONE); - } else { - v.setVisibility(View.VISIBLE); - } - } - - private Drawable getIcon1(Cursor cursor) { - if (mIconName1Col == INVALID_INDEX) { - return null; - } - String value = cursor.getString(mIconName1Col); - Drawable drawable = getDrawableFromResourceValue(value); - if (drawable != null) { - return drawable; - } - return getDefaultIcon1(cursor); - } - - private Drawable getIcon2(Cursor cursor) { - if (mIconName2Col == INVALID_INDEX) { - return null; - } - String value = cursor.getString(mIconName2Col); - return getDrawableFromResourceValue(value); - } - - /** - * Sets the drawable in an image view, makes sure the view is only visible if there - * is a drawable. - */ - private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) { - // Set the icon even if the drawable is null, since we need to clear any - // previous icon. - v.setImageDrawable(drawable); - - if (drawable == null) { - v.setVisibility(nullVisibility); - } else { - v.setVisibility(View.VISIBLE); - - // This is a hack to get any animated drawables (like a 'working' spinner) - // to animate. You have to setVisible true on an AnimationDrawable to get - // it to start animating, but it must first have been false or else the - // call to setVisible will be ineffective. We need to clear up the story - // about animated drawables in the future, see http://b/1878430. - drawable.setVisible(false, false); - drawable.setVisible(true, false); - } - } - - /** - * Gets the text to show in the query field when a suggestion is selected. - * - * @param cursor The Cursor to read the suggestion data from. The Cursor should already - * be moved to the suggestion that is to be read from. - * @return The text to show, or null if the query should not be - * changed when selecting this suggestion. - */ - @Override - public CharSequence convertToString(Cursor cursor) { - if (cursor == null) { - return null; - } - - String query = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_QUERY); - if (query != null) { - return query; - } - - return null; - } - - /** - * This method is overridden purely to provide a bit of protection against - * flaky content providers. - * - * @see android.widget.ListAdapter#getView(int, View, ViewGroup) - */ - @Override - public View getView(int position, View convertView, ViewGroup parent) { - try { - return super.getView(position, convertView, parent); - } catch (RuntimeException e) { - Log.w(LOG_TAG, "Search suggestions cursor threw exception.", e); - // Put exception string in item title - View v = newView(mContext, mCursor, parent); - if (v != null) { - ChildViewCache views = (ChildViewCache) v.getTag(); - TextView tv = views.mText1; - tv.setText(e.toString()); - } - return v; - } - } - - /** - * Gets a drawable given a value provided by a suggestion provider. - * - * This value could be just the string value of a resource id - * (e.g., "2130837524"), in which case we will try to retrieve a drawable from - * the provider's resources. If the value is not an integer, it is - * treated as a Uri and opened with - * {@link ContentResolver#openOutputStream(android.net.Uri, String)}. - * - * All resources and URIs are read using the suggestion provider's context. - * - * If the string is not formatted as expected, or no drawable can be found for - * the provided value, this method returns null. - * - * @param drawableId a string like "2130837524", - * "android.resource://com.android.alarmclock/2130837524", - * or "content://contacts/photos/253". - * @return a Drawable, or null if none found - */ - private Drawable getDrawableFromResourceValue(String drawableId) { - if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) { - return null; - } - try { - // First, see if it's just an integer - int resourceId = Integer.parseInt(drawableId); - // It's an int, look for it in the cache - String drawableUri = ContentResolver.SCHEME_ANDROID_RESOURCE - + "://" + mProviderContext.getPackageName() + "/" + resourceId; - // Must use URI as cache key, since ints are app-specific - Drawable drawable = checkIconCache(drawableUri); - if (drawable != null) { - return drawable; - } - // Not cached, find it by resource ID - drawable = mProviderContext.getResources().getDrawable(resourceId); - // Stick it in the cache, using the URI as key - storeInIconCache(drawableUri, drawable); - return drawable; - } catch (NumberFormatException nfe) { - // It's not an integer, use it as a URI - Drawable drawable = checkIconCache(drawableId); - if (drawable != null) { - return drawable; - } - Uri uri = Uri.parse(drawableId); - drawable = getDrawable(uri); - storeInIconCache(drawableId, drawable); - return drawable; - } catch (Resources.NotFoundException nfe) { - // It was an integer, but it couldn't be found, bail out - Log.w(LOG_TAG, "Icon resource not found: " + drawableId); - return null; - } - } - - /** - * Gets a drawable by URI, without using the cache. - * - * @return A drawable, or {@code null} if the drawable could not be loaded. - */ - private Drawable getDrawable(Uri uri) { - try { - String scheme = uri.getScheme(); - if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) { - // Load drawables through Resources, to get the source density information - try { - return getTheDrawable(uri); - } catch (Resources.NotFoundException ex) { - throw new FileNotFoundException("Resource does not exist: " + uri); - } - } else { - // Let the ContentResolver handle content and file URIs. - InputStream stream = mProviderContext.getContentResolver().openInputStream(uri); - if (stream == null) { - throw new FileNotFoundException("Failed to open " + uri); - } - try { - return Drawable.createFromStream(stream, null); - } finally { - try { - stream.close(); - } catch (IOException ex) { - Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex); - } - } - } - } catch (FileNotFoundException fnfe) { - Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage()); - return null; - } - } - - public Drawable getTheDrawable(Uri uri) throws FileNotFoundException { - String authority = uri.getAuthority(); - Resources r; - if (TextUtils.isEmpty(authority)) { - throw new FileNotFoundException("No authority: " + uri); - } else { - try { - r = mContext.getPackageManager().getResourcesForApplication(authority); - } catch (NameNotFoundException ex) { - throw new FileNotFoundException("No package found for authority: " + uri); - } - } - List path = uri.getPathSegments(); - if (path == null) { - throw new FileNotFoundException("No path: " + uri); - } - int len = path.size(); - int id; - if (len == 1) { - try { - id = Integer.parseInt(path.get(0)); - } catch (NumberFormatException e) { - throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); - } - } else if (len == 2) { - id = r.getIdentifier(path.get(1), path.get(0), authority); - } else { - throw new FileNotFoundException("More than two path segments: " + uri); - } - if (id == 0) { - throw new FileNotFoundException("No resource found for: " + uri); - } - return r.getDrawable(id); - } - - private Drawable checkIconCache(String resourceUri) { - Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri); - if (cached == null) { - return null; - } - if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri); - return cached.newDrawable(); - } - - private void storeInIconCache(String resourceUri, Drawable drawable) { - if (drawable != null) { - mOutsideDrawablesCache.put(resourceUri, drawable.getConstantState()); - } - } - - /** - * Gets the left-hand side icon that will be used for the current suggestion - * if the suggestion contains an icon column but no icon or a broken icon. - * - * @param cursor A cursor positioned at the current suggestion. - * @return A non-null drawable. - */ - private Drawable getDefaultIcon1(Cursor cursor) { - // Fall back to a default icon - return mContext.getPackageManager().getDefaultActivityIcon(); - } - - /** - * Gets the activity or application icon for an activity. - * Uses the local icon cache for fast repeated lookups. - * - * @param component Name of an activity. - * @return A drawable, or {@code null} if neither the activity nor the application - * has an icon set. - */ - private Drawable getActivityIconWithCache(ComponentName component) { - // First check the icon cache - String componentIconKey = component.flattenToShortString(); - // Using containsKey() since we also store null values. - if (mOutsideDrawablesCache.containsKey(componentIconKey)) { - Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey); - return cached == null ? null : cached.newDrawable(mProviderContext.getResources()); - } - // Then try the activity or application icon - Drawable drawable = getActivityIcon(component); - // Stick it in the cache so we don't do this lookup again. - Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState(); - mOutsideDrawablesCache.put(componentIconKey, toCache); - return drawable; - } - - /** - * Gets the activity or application icon for an activity. - * - * @param component Name of an activity. - * @return A drawable, or {@code null} if neither the acitivy or the application - * have an icon set. - */ - private Drawable getActivityIcon(ComponentName component) { - PackageManager pm = mContext.getPackageManager(); - final ActivityInfo activityInfo; - try { - activityInfo = pm.getActivityInfo(component, PackageManager.GET_META_DATA); - } catch (NameNotFoundException ex) { - Log.w(LOG_TAG, ex.toString()); - return null; - } - int iconId = activityInfo.getIconResource(); - if (iconId == 0) return null; - String pkg = component.getPackageName(); - Drawable drawable = pm.getDrawable(pkg, iconId, activityInfo.applicationInfo); - if (drawable == null) { - Log.w(LOG_TAG, "Invalid icon resource " + iconId + " for " - + component.flattenToShortString()); - return null; - } - return drawable; - } - - /** - * Gets the value of a string column by name. - * - * @param cursor Cursor to read the value from. - * @param columnName The name of the column to read. - * @return The value of the given column, or null - * if the cursor does not contain the given column. - */ - public static String getColumnString(Cursor cursor, String columnName) { - int col = cursor.getColumnIndex(columnName); - return getStringOrNull(cursor, col); - } - - private static String getStringOrNull(Cursor cursor, int col) { - if (col == INVALID_INDEX) { - return null; - } - try { - return cursor.getString(col); - } catch (Exception e) { - Log.e(LOG_TAG, - "unexpected error retrieving valid column from cursor, " - + "did the remote process die?", e); - return null; - } - } -} diff --git a/OpenPGP-Keychain/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java b/OpenPGP-Keychain/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java deleted file mode 100644 index 47475c574..000000000 --- a/OpenPGP-Keychain/android-libs/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.actionbarsherlock.internal; - -import org.junit.Test; - -import static com.actionbarsherlock.internal.ActionBarSherlockCompat.cleanActivityName; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; - -public class ManifestParsingTest { - @Test - public void testFullyQualifiedClassName() { - String expected = "com.other.package.SomeClass"; - String actual = cleanActivityName("com.jakewharton.test", "com.other.package.SomeClass"); - assertThat(expected, equalTo(actual)); - } - - @Test - public void testFullyQualifiedClassNameSamePackage() { - String expected = "com.jakewharton.test.SomeClass"; - String actual = cleanActivityName("com.jakewharton.test", "com.jakewharton.test.SomeClass"); - assertThat(expected, equalTo(actual)); - } - - @Test - public void testUnqualifiedClassName() { - String expected = "com.jakewharton.test.SomeClass"; - String actual = cleanActivityName("com.jakewharton.test", "SomeClass"); - assertThat(expected, equalTo(actual)); - } - - @Test - public void testRelativeClassName() { - String expected = "com.jakewharton.test.ui.SomeClass"; - String actual = cleanActivityName("com.jakewharton.test", ".ui.SomeClass"); - assertThat(expected, equalTo(actual)); - } -} \ No newline at end of file diff --git a/OpenPGP-Keychain/build.gradle b/OpenPGP-Keychain/build.gradle new file mode 100644 index 000000000..b9720f405 --- /dev/null +++ b/OpenPGP-Keychain/build.gradle @@ -0,0 +1,63 @@ +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:0.4' + } +} + +apply plugin: 'android' + +dependencies { + compile fileTree(dir: 'libs', includes: ['*.jar'], excludes: ['android-support-v4.jar']) + compile project(':libraries:ActionBarSherlock') +} + +android { + compileSdkVersion 17 + buildToolsVersion "17" + + defaultConfig { + minSdkVersion 8 + targetSdkVersion 17 + } + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + resources.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['assets'] + } + + instrumentTest.setRoot('tests') + } + + /* + * To sign release build, create file gradle.properties in .gradle/ with this content: + * + * signingStoreLocation=/home/key.store + * signingStorePassword=xxx + * signingKeyAlias=alias + * signingKeyPassword=xxx + */ + signingConfigs { + myConfig { + storeFile file(signingStoreLocation) + storePassword signingStorePassword + keyAlias signingKeyAlias + keyPassword signingKeyPassword + } + } + + buildTypes { + release { + signingConfig signingConfigs.myConfig + } + } +} diff --git a/OpenPGP-Keychain/libs/android-support-v4.jar b/OpenPGP-Keychain/libs/android-support-v4.jar new file mode 100644 index 000000000..99e063b33 Binary files /dev/null and b/OpenPGP-Keychain/libs/android-support-v4.jar differ diff --git a/OpenPGP-Keychain/project.properties b/OpenPGP-Keychain/project.properties index 2267fbaf8..cfb577df7 100644 --- a/OpenPGP-Keychain/project.properties +++ b/OpenPGP-Keychain/project.properties @@ -9,4 +9,4 @@ # Project target. target=android-17 -android.library.reference.1=android-libs/ActionBarSherlock +android.library.reference.1=../libraries/ActionBarSherlock diff --git a/libraries/ActionBarSherlock/.gitignore b/libraries/ActionBarSherlock/.gitignore new file mode 100644 index 000000000..71c11b159 --- /dev/null +++ b/libraries/ActionBarSherlock/.gitignore @@ -0,0 +1,30 @@ +#Android specific +bin +gen +obj +libs/armeabi +lint.xml +local.properties +release.properties +ant.properties +*.class +*.apk + +#Gradle +.gradle +build +gradle.properties + +#Maven +target +pom.xml.* + +#Eclipse +.project +.classpath +.settings +.metadata + +#IntelliJ IDEA +.idea +*.iml diff --git a/libraries/ActionBarSherlock/AndroidManifest.xml b/libraries/ActionBarSherlock/AndroidManifest.xml new file mode 100644 index 000000000..7b8a84824 --- /dev/null +++ b/libraries/ActionBarSherlock/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/libraries/ActionBarSherlock/README.md b/libraries/ActionBarSherlock/README.md new file mode 100644 index 000000000..e8a2c080e --- /dev/null +++ b/libraries/ActionBarSherlock/README.md @@ -0,0 +1,15 @@ +ActionBarSherlock Library +========================= + +This folder contains the main library which should be linked against as an +Android library project in your application. + +For more information see the "Including In Your Project" section of the +[usage page][1]. + + + + + + + [1]: http://actionbarsherlock.com/usage.html diff --git a/libraries/ActionBarSherlock/build.gradle b/libraries/ActionBarSherlock/build.gradle new file mode 100644 index 000000000..102d66946 --- /dev/null +++ b/libraries/ActionBarSherlock/build.gradle @@ -0,0 +1,27 @@ +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.4.1' + } +} + +apply plugin: 'android-library' + +dependencies { + compile files('libs/android-support-v4.jar') +} + +android { + compileSdkVersion 17 + buildToolsVersion '17' + + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + res.srcDirs = ['res'] + } + } +} diff --git a/libraries/ActionBarSherlock/build.xml b/libraries/ActionBarSherlock/build.xml new file mode 100644 index 000000000..a10a91491 --- /dev/null +++ b/libraries/ActionBarSherlock/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/libs/android-support-v4.jar b/libraries/ActionBarSherlock/libs/android-support-v4.jar new file mode 100644 index 000000000..99e063b33 Binary files /dev/null and b/libraries/ActionBarSherlock/libs/android-support-v4.jar differ diff --git a/libraries/ActionBarSherlock/pom.xml b/libraries/ActionBarSherlock/pom.xml new file mode 100644 index 000000000..3b6ce40ce --- /dev/null +++ b/libraries/ActionBarSherlock/pom.xml @@ -0,0 +1,148 @@ + + + + 4.0.0 + + actionbarsherlock + ActionBarSherlock + apklib + + + com.actionbarsherlock + parent + 4.2.0 + ../pom.xml + + + + + com.google.android + android + provided + + + com.google.android + support-v4 + + + + junit + junit + test + + + + + src + test + + + + com.jayway.maven.plugins.android.generation2 + android-maven-plugin + true + + ignored + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + true + + + + + com.google.code.maven-replacer-plugin + maven-replacer-plugin + 1.4.0 + + + process-sources + + replace + + + + + false + target/generated-sources/r/com/actionbarsherlock/R.java + target/generated-sources/r/com/actionbarsherlock/R.java + false + static final int + static int + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../checkstyle.xml + + + + verify + + checkstyle + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.7 + + + package + + attach-artifact + + + + + jar + ${project.build.directory}/${project.build.finalName}.jar + + + + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + com.google.code.maven-replacer-plugin + maven-replacer-plugin + [1.4.0,) + + replace + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/proguard-project.txt b/libraries/ActionBarSherlock/proguard-project.txt new file mode 100644 index 000000000..f2fe1559a --- /dev/null +++ b/libraries/ActionBarSherlock/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/libraries/ActionBarSherlock/project.properties b/libraries/ActionBarSherlock/project.properties new file mode 100644 index 000000000..5ca7d6247 --- /dev/null +++ b/libraries/ActionBarSherlock/project.properties @@ -0,0 +1,12 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +android.library=true +# Project target. +target=android-14 diff --git a/libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml b/libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml new file mode 100644 index 000000000..ea7459aaf --- /dev/null +++ b/libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_dark.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml b/libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml new file mode 100644 index 000000000..0edb33b4b --- /dev/null +++ b/libraries/ActionBarSherlock/res/color/abs__primary_text_disable_only_holo_light.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml b/libraries/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml new file mode 100644 index 000000000..2bcfd0b63 --- /dev/null +++ b/libraries/ActionBarSherlock/res/color/abs__primary_text_holo_dark.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml b/libraries/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml new file mode 100644 index 000000000..198384fed --- /dev/null +++ b/libraries/ActionBarSherlock/res/color/abs__primary_text_holo_light.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png new file mode 100644 index 000000000..769463b36 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png new file mode 100644 index 000000000..88f11dcb9 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_inverse_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png new file mode 100644 index 000000000..73050476e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 000000000..712a551ec Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png new file mode 100644 index 000000000..bf3b9438b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_bottom_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png new file mode 100644 index 000000000..81b87b86c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png new file mode 100644 index 000000000..8fc83e22e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_share_pack_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png new file mode 100644 index 000000000..cbbaec588 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png new file mode 100644 index 000000000..af917e5b6 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png new file mode 100644 index 000000000..2d59f354e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_solid_shadow_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png new file mode 100644 index 000000000..0520e5a2f Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png new file mode 100644 index 000000000..e3e3f93b9 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 000000000..1e3957222 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png new file mode 100644 index 000000000..a16db853e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_stacked_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png new file mode 100644 index 000000000..0eff695d8 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png new file mode 100644 index 000000000..219b170fa Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ab_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png new file mode 100644 index 000000000..b0dc31fb3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png new file mode 100644 index 000000000..4bc2683b1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png new file mode 100644 index 000000000..4af38fb70 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png new file mode 100644 index 000000000..d32f74cf4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_focused_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png new file mode 100644 index 000000000..66adffed6 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png new file mode 100644 index 000000000..caeff9c33 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__btn_cab_done_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png new file mode 100644 index 000000000..1d836f65a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png new file mode 100644 index 000000000..5818666d4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_bottom_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png new file mode 100644 index 000000000..564fb34b4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png new file mode 100644 index 000000000..ae21b760f Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__cab_background_top_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png new file mode 100644 index 000000000..79e56f522 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png new file mode 100644 index 000000000..e029f210b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__dialog_full_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png new file mode 100644 index 000000000..897a1c11a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png new file mode 100644 index 000000000..0c89f7140 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_ab_back_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png new file mode 100644 index 000000000..d8662e3f0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png new file mode 100644 index 000000000..ed03f620f Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_cab_done_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png new file mode 100644 index 000000000..d97c342d5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_disabled.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png new file mode 100644 index 000000000..33ad8d4b8 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_normal.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 000000000..3edbd7408 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_disabled_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png new file mode 100644 index 000000000..90db01b5b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_clear_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png new file mode 100644 index 000000000..97b825e83 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png new file mode 100644 index 000000000..7e1ba2adc Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_go_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 000000000..2abc45809 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 000000000..bb6aef1d0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png new file mode 100644 index 000000000..6f747c8f0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png new file mode 100644 index 000000000..682b2fdec Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_menu_share_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png new file mode 100644 index 000000000..4be72f108 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png new file mode 100644 index 000000000..72e207bc5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png new file mode 100644 index 000000000..66d14aec0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png new file mode 100644 index 000000000..3481c9828 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__ic_voice_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png new file mode 100644 index 000000000..4ea7afa00 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_activated_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png new file mode 100644 index 000000000..986ab0b97 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png new file mode 100644 index 000000000..0279e17a1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_divider_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png new file mode 100644 index 000000000..516f5c739 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_focused_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png new file mode 100644 index 000000000..4ea7afa00 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_longpressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png new file mode 100644 index 000000000..5654cd694 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png new file mode 100644 index 000000000..5654cd694 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png new file mode 100644 index 000000000..f6fd30dcd Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png new file mode 100644 index 000000000..ca8e9a277 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__list_selector_disabled_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 000000000..4d3d20857 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png new file mode 100644 index 000000000..924a99d17 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__menu_dropdown_panel_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png new file mode 100644 index 000000000..310c368e7 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png new file mode 100644 index 000000000..70cb7fc7e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_bg_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png new file mode 100644 index 000000000..1c269205e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png new file mode 100644 index 000000000..1c269205e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_primary_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png new file mode 100644 index 000000000..40d0d1645 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png new file mode 100644 index 000000000..40d0d1645 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__progress_secondary_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png new file mode 100644 index 000000000..c8358e9ce Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_inner_holo.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png new file mode 100644 index 000000000..f62f74bb3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_48_outer_holo.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png new file mode 100644 index 000000000..eb28ff9a5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png new file mode 100644 index 000000000..d281adb55 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 000000000..b29858609 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png new file mode 100644 index 000000000..4215396dd Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_disabled_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png new file mode 100644 index 000000000..a280eabf5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png new file mode 100644 index 000000000..f8d619b4d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_focused_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 000000000..955a2f340 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png new file mode 100644 index 000000000..6c22e223a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__spinner_ab_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png new file mode 100644 index 000000000..673e3bf10 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_focused_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png new file mode 100644 index 000000000..d57df98b5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png new file mode 100644 index 000000000..6278eef47 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_selected_pressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png new file mode 100644 index 000000000..aadc6f87b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__tab_unselected_pressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png new file mode 100644 index 000000000..70c0e7396 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png new file mode 100644 index 000000000..36e71d85d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png new file mode 100644 index 000000000..4be4af5fa Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png new file mode 100644 index 000000000..e72193f59 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 000000000..8f20b9d26 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png new file mode 100644 index 000000000..04f657e1d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_right_selected_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png new file mode 100644 index 000000000..99309ef6d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png new file mode 100644 index 000000000..9bde7fbdc Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-hdpi/abs__textfield_search_selected_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png new file mode 100644 index 000000000..b2293670b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png new file mode 100644 index 000000000..c65f443e3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_inverse_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png new file mode 100644 index 000000000..0706c8af6 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 000000000..d814d02d3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png new file mode 100644 index 000000000..b139c8e49 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_bottom_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png new file mode 100644 index 000000000..738cb38d0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png new file mode 100644 index 000000000..2ed75a767 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_share_pack_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png new file mode 100644 index 000000000..743d00b6c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png new file mode 100644 index 000000000..17c1fb921 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png new file mode 100644 index 000000000..ddfc8e3d5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_solid_shadow_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png new file mode 100644 index 000000000..007a4b239 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png new file mode 100644 index 000000000..ad6e1a4d9 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 000000000..0ad6c888b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png new file mode 100644 index 000000000..19b50abcb Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_stacked_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png new file mode 100644 index 000000000..ad980b13f Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png new file mode 100644 index 000000000..60e6c5278 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ab_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png new file mode 100644 index 000000000..5461b9c00 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png new file mode 100644 index 000000000..5dc6f804a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png new file mode 100644 index 000000000..a70b53c59 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png new file mode 100644 index 000000000..c7a9896b0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_focused_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png new file mode 100644 index 000000000..85d7aadd4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png new file mode 100644 index 000000000..f7b01e012 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__btn_cab_done_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png new file mode 100644 index 000000000..d8f1c8bd5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png new file mode 100644 index 000000000..31e49894a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_bottom_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png new file mode 100644 index 000000000..7c2cbe535 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png new file mode 100644 index 000000000..30cbdc174 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__cab_background_top_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png new file mode 100644 index 000000000..fb3660eab Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png new file mode 100644 index 000000000..f18050ea5 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__dialog_full_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png new file mode 100644 index 000000000..df2d3d158 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png new file mode 100644 index 000000000..b2aa9c265 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_ab_back_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png new file mode 100644 index 000000000..a17b6a789 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png new file mode 100644 index 000000000..b28b3b54f Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_cab_done_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png new file mode 100644 index 000000000..79228baed Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_disabled.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png new file mode 100644 index 000000000..86944a879 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_normal.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 000000000..c0bdf0641 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_disabled_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png new file mode 100644 index 000000000..15b86cbb2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_clear_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png new file mode 100644 index 000000000..bf19833f2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png new file mode 100644 index 000000000..8518498eb Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_go_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 000000000..ba704b67e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 000000000..01d681697 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png new file mode 100644 index 000000000..6bf21e307 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png new file mode 100644 index 000000000..70fe31aa2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_menu_share_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png new file mode 100644 index 000000000..4be72f108 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png new file mode 100644 index 000000000..f2e26f883 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png new file mode 100644 index 000000000..73c6be654 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png new file mode 100644 index 000000000..71d838e73 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__ic_voice_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png new file mode 100644 index 000000000..3bf8e0362 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_activated_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png new file mode 100644 index 000000000..986ab0b97 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png new file mode 100644 index 000000000..0279e17a1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_divider_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png new file mode 100644 index 000000000..7c0599e3a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_focused_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png new file mode 100644 index 000000000..3bf8e0362 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_longpressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png new file mode 100644 index 000000000..6e77525d2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png new file mode 100644 index 000000000..6e77525d2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png new file mode 100644 index 000000000..92da2f0dd Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png new file mode 100644 index 000000000..42cb6463e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__list_selector_disabled_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 000000000..460ec46eb Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png new file mode 100644 index 000000000..e84adf2d4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__menu_dropdown_panel_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png new file mode 100644 index 000000000..3d946e545 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png new file mode 100644 index 000000000..4bb22f0e1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_bg_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png new file mode 100644 index 000000000..ab8ec6984 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png new file mode 100644 index 000000000..ab8ec6984 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_primary_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png new file mode 100644 index 000000000..7274274b1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png new file mode 100644 index 000000000..7274274b1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__progress_secondary_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png new file mode 100644 index 000000000..9458668f0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_inner_holo.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png new file mode 100644 index 000000000..4ce73edce Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_48_outer_holo.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png new file mode 100644 index 000000000..29aff4d43 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png new file mode 100644 index 000000000..4055f7053 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 000000000..ea4ee042e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png new file mode 100644 index 000000000..f74c02b9e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_disabled_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png new file mode 100644 index 000000000..09a2992cc Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png new file mode 100644 index 000000000..6536ee633 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_focused_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 000000000..202b5b72e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png new file mode 100644 index 000000000..6de0ba884 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__spinner_ab_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png new file mode 100644 index 000000000..c9972e74b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_focused_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png new file mode 100644 index 000000000..587337caf Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png new file mode 100644 index 000000000..155c4fc75 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_selected_pressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png new file mode 100644 index 000000000..b1223fe3c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__tab_unselected_pressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png new file mode 100644 index 000000000..081657ee7 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png new file mode 100644 index 000000000..3f312b465 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png new file mode 100644 index 000000000..b086fae87 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png new file mode 100644 index 000000000..73c336a77 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 000000000..726e0ff42 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png new file mode 100644 index 000000000..726e0ff42 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_right_selected_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png new file mode 100644 index 000000000..1767c169e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png new file mode 100644 index 000000000..1767c169e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-mdpi/abs__textfield_search_selected_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml b/libraries/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml new file mode 100644 index 000000000..6bcbdb83f --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable-v11/abs__progress_medium_holo.xml @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png new file mode 100644 index 000000000..575334699 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png new file mode 100644 index 000000000..7e6c047d6 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_inverse_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png new file mode 100644 index 000000000..8155fe840 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png new file mode 100644 index 000000000..6cee9a128 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png new file mode 100644 index 000000000..fa4d76af9 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_bottom_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png new file mode 100644 index 000000000..9a70a5d1e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png new file mode 100644 index 000000000..14fbee101 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_share_pack_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png new file mode 100644 index 000000000..6622cbad3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png new file mode 100644 index 000000000..c42729783 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png new file mode 100644 index 000000000..d0df29d8b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_solid_shadow_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png new file mode 100644 index 000000000..a0d9c1b95 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png new file mode 100644 index 000000000..d36f99fec Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_solid_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png new file mode 100644 index 000000000..5ad475dc3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png new file mode 100644 index 000000000..6ade5eeb3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_stacked_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png new file mode 100644 index 000000000..719b9234d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_dark_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png new file mode 100644 index 000000000..6da264db2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ab_transparent_light_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png new file mode 100644 index 000000000..7ef2db75e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png new file mode 100644 index 000000000..2283b4c01 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png new file mode 100644 index 000000000..6d2039e28 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png new file mode 100644 index 000000000..3c909b513 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_focused_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png new file mode 100644 index 000000000..131d1030c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png new file mode 100644 index 000000000..3e7dcdfdb Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__btn_cab_done_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png new file mode 100644 index 000000000..0bd09806f Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png new file mode 100644 index 000000000..43ed26d47 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_bottom_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png new file mode 100644 index 000000000..6b3157985 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png new file mode 100644 index 000000000..df0121bb3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__cab_background_top_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png new file mode 100644 index 000000000..f4970ad1c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png new file mode 100644 index 000000000..172fc3b5e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__dialog_full_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png new file mode 100644 index 000000000..8ded62fb7 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png new file mode 100644 index 000000000..517e9f72d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_ab_back_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png new file mode 100644 index 000000000..2e06dd01b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png new file mode 100644 index 000000000..bb19810bc Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_cab_done_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png new file mode 100644 index 000000000..e35c5f05e Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_disabled.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png new file mode 100644 index 000000000..7fd7aeb2a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_disabled_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png new file mode 100644 index 000000000..53cfbd311 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_clear_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png new file mode 100644 index 000000000..1e2dcfa02 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png new file mode 100644 index 000000000..f12eafcdc Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_go_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png new file mode 100644 index 000000000..a92fb1d4a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png new file mode 100644 index 000000000..930ca8d95 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_moreoverflow_normal_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png new file mode 100644 index 000000000..45a0f1da0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_dark.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png new file mode 100644 index 000000000..528e554ab Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_menu_share_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png new file mode 100644 index 000000000..998f91be9 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png new file mode 100644 index 000000000..a4cdf1c79 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png new file mode 100644 index 000000000..c625a3602 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png new file mode 100644 index 000000000..c332ba08c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__ic_voice_search_api_holo_light.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png new file mode 100644 index 000000000..eda10e612 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_activated_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png new file mode 100644 index 000000000..e62f011d4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png new file mode 100644 index 000000000..65061c0f4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_divider_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png new file mode 100644 index 000000000..690cb1eb6 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_focused_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png new file mode 100644 index 000000000..eda10e612 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_longpressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png new file mode 100644 index 000000000..e4b33935a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png new file mode 100644 index 000000000..e4b33935a Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png new file mode 100644 index 000000000..88726b691 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png new file mode 100644 index 000000000..c6a7d4d87 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__list_selector_disabled_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png new file mode 100644 index 000000000..e2aff72f4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png new file mode 100644 index 000000000..93066c840 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__menu_dropdown_panel_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png new file mode 100644 index 000000000..345f5d306 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png new file mode 100644 index 000000000..c843ef3af Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_bg_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png new file mode 100644 index 000000000..c6c3f1ec2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png new file mode 100644 index 000000000..c6c3f1ec2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_primary_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png new file mode 100644 index 000000000..205b66e2c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png new file mode 100644 index 000000000..205b66e2c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__progress_secondary_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png new file mode 100644 index 000000000..19517c4b0 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_inner_holo.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png new file mode 100644 index 000000000..14143c51c Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_48_outer_holo.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png new file mode 100644 index 000000000..d8929fcd1 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png new file mode 100644 index 000000000..9174c4e4b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png new file mode 100644 index 000000000..3015d3070 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png new file mode 100644 index 000000000..126637d11 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_disabled_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png new file mode 100644 index 000000000..d45c7a864 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png new file mode 100644 index 000000000..29036b907 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_focused_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png new file mode 100644 index 000000000..2cb34d7f6 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png new file mode 100644 index 000000000..82f752fdc Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__spinner_ab_pressed_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png new file mode 100644 index 000000000..03cfb0945 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_focused_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png new file mode 100644 index 000000000..e4229f26b Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png new file mode 100644 index 000000000..e862cb121 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_selected_pressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png new file mode 100644 index 000000000..f1eb67323 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__tab_unselected_pressed_holo.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png new file mode 100644 index 000000000..8fdbbf3ad Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png new file mode 100644 index 000000000..4e9ae43c2 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png new file mode 100644 index 000000000..98f4871bb Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png new file mode 100644 index 000000000..733373ed3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_default_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png new file mode 100644 index 000000000..0c6bb036d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png new file mode 100644 index 000000000..0c6bb036d Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_right_selected_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png new file mode 100644 index 000000000..e5bfd8ad3 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_dark.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png new file mode 100644 index 000000000..1743da6b4 Binary files /dev/null and b/libraries/ActionBarSherlock/res/drawable-xhdpi/abs__textfield_search_selected_holo_light.9.png differ diff --git a/libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml new file mode 100644 index 000000000..85c2c0212 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_dark.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml new file mode 100644 index 000000000..85c2c0212 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__activated_background_holo_light.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml new file mode 100644 index 000000000..cab896283 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_dark.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml new file mode 100644 index 000000000..42ba8a0df --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__btn_cab_done_holo_light.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__ic_clear.xml b/libraries/ActionBarSherlock/res/drawable/abs__ic_clear.xml new file mode 100644 index 000000000..a16f4b22e --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__ic_clear.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml new file mode 100644 index 000000000..256de80fb --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__ic_clear_holo_light.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml new file mode 100644 index 000000000..2588a492d --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_dark.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml new file mode 100644 index 000000000..e2078c967 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__ic_menu_moreoverflow_holo_light.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml new file mode 100644 index 000000000..d99b7a426 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_dark.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml new file mode 100644 index 000000000..da5fb2e86 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__item_background_holo_light.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml new file mode 100644 index 000000000..b2ce4f0f7 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_dark.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml new file mode 100644 index 000000000..d7e31b1d1 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_background_transition_holo_light.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml new file mode 100644 index 000000000..08b8b12f3 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_dark.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml new file mode 100644 index 000000000..ada490bf9 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__list_selector_holo_light.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml new file mode 100644 index 000000000..bd19140ab --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_dark.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml new file mode 100644 index 000000000..321f07c8b --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__progress_horizontal_holo_light.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml b/libraries/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml new file mode 100644 index 000000000..6d4814f86 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__progress_medium_holo.xml @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml new file mode 100644 index 000000000..26284187a --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_dark.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml new file mode 100644 index 000000000..0d00c5878 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__search_dropdown_light.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml new file mode 100644 index 000000000..4af5e22a9 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_dark.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml new file mode 100644 index 000000000..b78508478 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__spinner_ab_holo_light.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml b/libraries/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml new file mode 100644 index 000000000..d34e20811 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__tab_indicator_ab_holo.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml new file mode 100644 index 000000000..b6d58c040 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_dark.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml new file mode 100644 index 000000000..3d6acf808 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_holo_light.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml new file mode 100644 index 000000000..05ff4eda5 --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_dark.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml new file mode 100644 index 000000000..f6d61e57a --- /dev/null +++ b/libraries/ActionBarSherlock/res/drawable/abs__textfield_searchview_right_holo_light.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml b/libraries/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml new file mode 100644 index 000000000..8811dad8d --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout-large/abs__action_mode_close_item.xml @@ -0,0 +1,40 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml b/libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml new file mode 100644 index 000000000..6c183c059 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_dropdown_item.xml @@ -0,0 +1,26 @@ + + + diff --git a/libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml b/libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml new file mode 100644 index 000000000..61dc02527 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout-v14/sherlock_spinner_item.xml @@ -0,0 +1,26 @@ + + + diff --git a/libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml b/libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml new file mode 100644 index 000000000..040df44ab --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml b/libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml new file mode 100644 index 000000000..c64ef141b --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout-xlarge/abs__screen_action_bar_overlay.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_bar_home.xml b/libraries/ActionBarSherlock/res/layout/abs__action_bar_home.xml new file mode 100644 index 000000000..5c1e9ec4b --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_bar_home.xml @@ -0,0 +1,38 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_bar_tab.xml b/libraries/ActionBarSherlock/res/layout/abs__action_bar_tab.xml new file mode 100644 index 000000000..f46f7a044 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_bar_tab.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml b/libraries/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml new file mode 100644 index 000000000..0d51220c9 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_bar_tab_bar_view.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml b/libraries/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml new file mode 100644 index 000000000..dd69acada --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_bar_title_item.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml b/libraries/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml new file mode 100644 index 000000000..13149fd63 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_menu_item_layout.xml @@ -0,0 +1,56 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_menu_layout.xml b/libraries/ActionBarSherlock/res/layout/abs__action_menu_layout.xml new file mode 100644 index 000000000..a6f8e53f8 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_menu_layout.xml @@ -0,0 +1,23 @@ + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_mode_bar.xml b/libraries/ActionBarSherlock/res/layout/abs__action_mode_bar.xml new file mode 100644 index 000000000..7168dc77f --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_mode_bar.xml @@ -0,0 +1,24 @@ + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml b/libraries/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml new file mode 100644 index 000000000..875ec3e1b --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__action_mode_close_item.xml @@ -0,0 +1,31 @@ + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml b/libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml new file mode 100644 index 000000000..6a0ac9ece --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml b/libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml new file mode 100644 index 000000000..b430032a1 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__activity_chooser_view_list_item.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml b/libraries/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml new file mode 100644 index 000000000..ab2b0ee6c --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__dialog_title_holo.xml @@ -0,0 +1,46 @@ + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml new file mode 100644 index 000000000..39aca3a8d --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_checkbox.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml new file mode 100644 index 000000000..55ab28a24 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_icon.xml @@ -0,0 +1,28 @@ + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml new file mode 100644 index 000000000..147f36fe8 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_layout.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml new file mode 100644 index 000000000..ff54bbecd --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__list_menu_item_radio.xml @@ -0,0 +1,24 @@ + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml b/libraries/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml new file mode 100644 index 000000000..d42425ad3 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__popup_menu_item_layout.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__screen_action_bar.xml b/libraries/ActionBarSherlock/res/layout/abs__screen_action_bar.xml new file mode 100644 index 000000000..1fb82fe9a --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__screen_action_bar.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml b/libraries/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml new file mode 100644 index 000000000..0961ef561 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__screen_action_bar_overlay.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__screen_simple.xml b/libraries/ActionBarSherlock/res/layout/abs__screen_simple.xml new file mode 100644 index 000000000..33e2dea0d --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__screen_simple.xml @@ -0,0 +1,38 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml b/libraries/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml new file mode 100644 index 000000000..f8b9fb185 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__screen_simple_overlay_action_mode.xml @@ -0,0 +1,38 @@ + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml b/libraries/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml new file mode 100644 index 000000000..e1d3dc49c --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__search_dropdown_item_icons_2line.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__search_view.xml b/libraries/ActionBarSherlock/res/layout/abs__search_view.xml new file mode 100644 index 000000000..6ba319121 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__search_view.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml b/libraries/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml new file mode 100644 index 000000000..8fc0eb12c --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/abs__simple_dropdown_hint.xml @@ -0,0 +1,29 @@ + + + diff --git a/libraries/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml b/libraries/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml new file mode 100644 index 000000000..a6c6252d2 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/sherlock_spinner_dropdown_item.xml @@ -0,0 +1,26 @@ + + + diff --git a/libraries/ActionBarSherlock/res/layout/sherlock_spinner_item.xml b/libraries/ActionBarSherlock/res/layout/sherlock_spinner_item.xml new file mode 100644 index 000000000..bea740178 --- /dev/null +++ b/libraries/ActionBarSherlock/res/layout/sherlock_spinner_item.xml @@ -0,0 +1,26 @@ + + + diff --git a/libraries/ActionBarSherlock/res/values-land/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-land/abs__dimens.xml new file mode 100644 index 000000000..502cc16a3 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-land/abs__dimens.xml @@ -0,0 +1,33 @@ + + + + + 40dip + + 4dip + + 16dp + + 12dp + + -2dp + + 4dip + diff --git a/libraries/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml new file mode 100644 index 000000000..3312cfa7f --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-large-hdpi-1024x600/abs__dimens.xml @@ -0,0 +1,33 @@ + + + + + 48dip + + 8dip + + 18dp + + 14dp + + -3dp + + 5dip + diff --git a/libraries/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml new file mode 100644 index 000000000..502cc16a3 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-large-land-hdpi-1024x600/abs__dimens.xml @@ -0,0 +1,33 @@ + + + + + 40dip + + 4dip + + 16dp + + 12dp + + -2dp + + 4dip + diff --git a/libraries/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml new file mode 100644 index 000000000..3312cfa7f --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-large-land-mdpi-1024x600/abs__dimens.xml @@ -0,0 +1,33 @@ + + + + + 48dip + + 8dip + + 18dp + + 14dp + + -3dp + + 5dip + diff --git a/libraries/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml new file mode 100644 index 000000000..35910333b --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-large-mdpi-1024x600/abs__dimens.xml @@ -0,0 +1,36 @@ + + + + + 56dip + + 4dip + + 18dp + + 14dp + + -3dp + + 9dip + + + 64dip + diff --git a/libraries/ActionBarSherlock/res/values-large/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-large/abs__dimens.xml new file mode 100644 index 000000000..63b12f7f3 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-large/abs__dimens.xml @@ -0,0 +1,29 @@ + + + + + 55% + + 80% + diff --git a/libraries/ActionBarSherlock/res/values-sw600dp/abs__bools.xml b/libraries/ActionBarSherlock/res/values-sw600dp/abs__bools.xml new file mode 100644 index 000000000..7a48e1542 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-sw600dp/abs__bools.xml @@ -0,0 +1,19 @@ + + + + + false + diff --git a/libraries/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml new file mode 100644 index 000000000..f67853817 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-sw600dp/abs__dimens.xml @@ -0,0 +1,38 @@ + + + + + 56dip + + 4dip + + 18dp + + 14dp + + -3dp + + 9dip + + 5 + + + 64dip + diff --git a/libraries/ActionBarSherlock/res/values-v11/abs__themes.xml b/libraries/ActionBarSherlock/res/values-v11/abs__themes.xml new file mode 100644 index 000000000..03473572c --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-v11/abs__themes.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/libraries/ActionBarSherlock/res/values-v14/abs__styles.xml b/libraries/ActionBarSherlock/res/values-v14/abs__styles.xml new file mode 100644 index 000000000..88a60dd92 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-v14/abs__styles.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/values-v14/abs__themes.xml b/libraries/ActionBarSherlock/res/values-v14/abs__themes.xml new file mode 100644 index 000000000..5fac1ab58 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-v14/abs__themes.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/values-w360dp/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-w360dp/abs__dimens.xml new file mode 100644 index 000000000..6f49d7e47 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-w360dp/abs__dimens.xml @@ -0,0 +1,22 @@ + + + + 3 + diff --git a/libraries/ActionBarSherlock/res/values-w480dp/abs__bools.xml b/libraries/ActionBarSherlock/res/values-w480dp/abs__bools.xml new file mode 100644 index 000000000..3eaf4aee9 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-w480dp/abs__bools.xml @@ -0,0 +1,22 @@ + + + + true + false + diff --git a/libraries/ActionBarSherlock/res/values-w480dp/abs__config.xml b/libraries/ActionBarSherlock/res/values-w480dp/abs__config.xml new file mode 100644 index 000000000..88357b0a7 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-w480dp/abs__config.xml @@ -0,0 +1,29 @@ + + + + + + + + true + + diff --git a/libraries/ActionBarSherlock/res/values-w500dp/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-w500dp/abs__dimens.xml new file mode 100644 index 000000000..2fd4deea2 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-w500dp/abs__dimens.xml @@ -0,0 +1,22 @@ + + + + 4 + diff --git a/libraries/ActionBarSherlock/res/values-w600dp/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-w600dp/abs__dimens.xml new file mode 100644 index 000000000..b085952d3 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-w600dp/abs__dimens.xml @@ -0,0 +1,22 @@ + + + + 5 + diff --git a/libraries/ActionBarSherlock/res/values-xlarge/abs__dimens.xml b/libraries/ActionBarSherlock/res/values-xlarge/abs__dimens.xml new file mode 100644 index 000000000..bfc535de1 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values-xlarge/abs__dimens.xml @@ -0,0 +1,45 @@ + + + + + 56dip + + 4dip + + 18dp + + 14dp + + -3dp + + 9dip + + + 64dip + + + 45% + + 72% + diff --git a/libraries/ActionBarSherlock/res/values/abs__attrs.xml b/libraries/ActionBarSherlock/res/values/abs__attrs.xml new file mode 100644 index 000000000..32631ca8d --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__attrs.xml @@ -0,0 +1,432 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/values/abs__bools.xml b/libraries/ActionBarSherlock/res/values/abs__bools.xml new file mode 100644 index 000000000..0b432448d --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__bools.xml @@ -0,0 +1,22 @@ + + + + + false + true + true + + diff --git a/libraries/ActionBarSherlock/res/values/abs__colors.xml b/libraries/ActionBarSherlock/res/values/abs__colors.xml new file mode 100644 index 000000000..625c632ff --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__colors.xml @@ -0,0 +1,27 @@ + + + + + #ff000000 + #fff3f3f3 + @color/abs__background_holo_light + @color/abs__background_holo_dark + #ff4c4c4c + #ffb2b2b2 + @color/abs__bright_foreground_holo_light + @color/abs__bright_foreground_holo_dark + #ff33b5e5 + diff --git a/libraries/ActionBarSherlock/res/values/abs__config.xml b/libraries/ActionBarSherlock/res/values/abs__config.xml new file mode 100644 index 000000000..4c7b5d459 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__config.xml @@ -0,0 +1,43 @@ + + + + + + + + 320dp + + + false + + + true + + + false + + diff --git a/libraries/ActionBarSherlock/res/values/abs__dimens.xml b/libraries/ActionBarSherlock/res/values/abs__dimens.xml new file mode 100644 index 000000000..831289e07 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__dimens.xml @@ -0,0 +1,67 @@ + + + + + 48dip + + 8dip + + 18dp + + 14dp + + -3dp + + 5dip + + 2 + + + 56dip + + + 64dip + + + 65% + + 95% + + + + 8dip + + + 8dip + + + 32dip + + + + 160dip + + + 320dip + diff --git a/libraries/ActionBarSherlock/res/values/abs__ids.xml b/libraries/ActionBarSherlock/res/values/abs__ids.xml new file mode 100644 index 000000000..f9f56045b --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__ids.xml @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/values/abs__strings.xml b/libraries/ActionBarSherlock/res/values/abs__strings.xml new file mode 100644 index 000000000..06a2a2af4 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__strings.xml @@ -0,0 +1,53 @@ + + + + + Navigate home + + Navigate up + + More options + + + Done + + + See all... + + Select activity + + Share with... + + Choose an application + + Share with + + Share with %s + + + Search + + Search query + + Clear query + + Submit query + + Voice search + diff --git a/libraries/ActionBarSherlock/res/values/abs__styles.xml b/libraries/ActionBarSherlock/res/values/abs__styles.xml new file mode 100644 index 000000000..45a18c183 --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__styles.xml @@ -0,0 +1,412 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/res/values/abs__themes.xml b/libraries/ActionBarSherlock/res/values/abs__themes.xml new file mode 100644 index 000000000..634fa798b --- /dev/null +++ b/libraries/ActionBarSherlock/res/values/abs__themes.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/ActionBarSherlock/src/android/support/v4/app/Watson.java b/libraries/ActionBarSherlock/src/android/support/v4/app/Watson.java new file mode 100644 index 000000000..d93de4c6a --- /dev/null +++ b/libraries/ActionBarSherlock/src/android/support/v4/app/Watson.java @@ -0,0 +1,144 @@ +package android.support.v4.app; + +import android.util.Log; +import android.view.View; +import android.view.Window; +import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; +import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; +import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +import java.util.ArrayList; + +/** I'm in ur package. Stealing ur variables. */ +public abstract class Watson extends FragmentActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener { + private static final boolean DEBUG = false; + private static final String TAG = "Watson"; + + /** Fragment interface for menu creation callback. */ + public interface OnCreateOptionsMenuListener { + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater); + } + /** Fragment interface for menu preparation callback. */ + public interface OnPrepareOptionsMenuListener { + public void onPrepareOptionsMenu(Menu menu); + } + /** Fragment interface for menu item selection callback. */ + public interface OnOptionsItemSelectedListener { + public boolean onOptionsItemSelected(MenuItem item); + } + + private ArrayList mCreatedMenus; + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] featureId: " + featureId + ", menu: " + menu); + + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + boolean result = onCreateOptionsMenu(menu); + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] activity create result: " + result); + + MenuInflater inflater = getSupportMenuInflater(); + boolean show = false; + ArrayList newMenus = null; + if (mFragments.mAdded != null) { + for (int i = 0; i < mFragments.mAdded.size(); i++) { + Fragment f = mFragments.mAdded.get(i); + if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnCreateOptionsMenuListener) { + show = true; + ((OnCreateOptionsMenuListener)f).onCreateOptionsMenu(menu, inflater); + if (newMenus == null) { + newMenus = new ArrayList(); + } + newMenus.add(f); + } + } + } + + if (mCreatedMenus != null) { + for (int i = 0; i < mCreatedMenus.size(); i++) { + Fragment f = mCreatedMenus.get(i); + if (newMenus == null || !newMenus.contains(f)) { + f.onDestroyOptionsMenu(); + } + } + } + + mCreatedMenus = newMenus; + + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] fragments create result: " + show); + result |= show; + + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] returning " + result); + return result; + } + return false; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (DEBUG) Log.d(TAG, "[onPreparePanel] featureId: " + featureId + ", view: " + view + " menu: " + menu); + + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + boolean result = onPrepareOptionsMenu(menu); + if (DEBUG) Log.d(TAG, "[onPreparePanel] activity prepare result: " + result); + + boolean show = false; + if (mFragments.mAdded != null) { + for (int i = 0; i < mFragments.mAdded.size(); i++) { + Fragment f = mFragments.mAdded.get(i); + if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnPrepareOptionsMenuListener) { + show = true; + ((OnPrepareOptionsMenuListener)f).onPrepareOptionsMenu(menu); + } + } + } + + if (DEBUG) Log.d(TAG, "[onPreparePanel] fragments prepare result: " + show); + result |= show; + + result &= menu.hasVisibleItems(); + if (DEBUG) Log.d(TAG, "[onPreparePanel] returning " + result); + return result; + } + return false; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] featureId: " + featureId + ", item: " + item); + + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + if (onOptionsItemSelected(item)) { + return true; + } + + if (mFragments.mAdded != null) { + for (int i = 0; i < mFragments.mAdded.size(); i++) { + Fragment f = mFragments.mAdded.get(i); + if (f != null && !f.mHidden && f.mHasMenu && f.mMenuVisible && f instanceof OnOptionsItemSelectedListener) { + if (((OnOptionsItemSelectedListener)f).onOptionsItemSelected(item)) { + return true; + } + } + } + } + } + return false; + } + + public abstract boolean onCreateOptionsMenu(Menu menu); + + public abstract boolean onPrepareOptionsMenu(Menu menu); + + public abstract boolean onOptionsItemSelected(MenuItem item); + + public abstract MenuInflater getSupportMenuInflater(); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java new file mode 100644 index 000000000..ab160f836 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/ActionBarSherlock.java @@ -0,0 +1,794 @@ +package com.actionbarsherlock; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Iterator; +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.os.Build; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.internal.ActionBarSherlockCompat; +import com.actionbarsherlock.internal.ActionBarSherlockNative; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +/** + *

Helper for implementing the action bar design pattern across all versions + * of Android.

+ * + *

This class will manage interaction with a custom action bar based on the + * Android 4.0 source code. The exposed API mirrors that of its native + * counterpart and you should refer to its documentation for instruction.

+ * + * @author Jake Wharton + */ +public abstract class ActionBarSherlock { + protected static final String TAG = "ActionBarSherlock"; + protected static final boolean DEBUG = false; + + private static final Class[] CONSTRUCTOR_ARGS = new Class[] { Activity.class, int.class }; + private static final HashMap> IMPLEMENTATIONS = + new HashMap>(); + + static { + //Register our two built-in implementations + registerImplementation(ActionBarSherlockCompat.class); + registerImplementation(ActionBarSherlockNative.class); + } + + + /** + *

Denotes an implementation of ActionBarSherlock which provides an + * action bar-enhanced experience.

+ */ + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + public @interface Implementation { + static final int DEFAULT_API = -1; + static final int DEFAULT_DPI = -1; + + int api() default DEFAULT_API; + int dpi() default DEFAULT_DPI; + } + + + /** Activity interface for menu creation callback. */ + public interface OnCreatePanelMenuListener { + public boolean onCreatePanelMenu(int featureId, Menu menu); + } + /** Activity interface for menu creation callback. */ + public interface OnCreateOptionsMenuListener { + public boolean onCreateOptionsMenu(Menu menu); + } + /** Activity interface for menu item selection callback. */ + public interface OnMenuItemSelectedListener { + public boolean onMenuItemSelected(int featureId, MenuItem item); + } + /** Activity interface for menu item selection callback. */ + public interface OnOptionsItemSelectedListener { + public boolean onOptionsItemSelected(MenuItem item); + } + /** Activity interface for menu preparation callback. */ + public interface OnPreparePanelListener { + public boolean onPreparePanel(int featureId, View view, Menu menu); + } + /** Activity interface for menu preparation callback. */ + public interface OnPrepareOptionsMenuListener { + public boolean onPrepareOptionsMenu(Menu menu); + } + /** Activity interface for action mode finished callback. */ + public interface OnActionModeFinishedListener { + public void onActionModeFinished(ActionMode mode); + } + /** Activity interface for action mode started callback. */ + public interface OnActionModeStartedListener { + public void onActionModeStarted(ActionMode mode); + } + + + /** + * If set, the logic in these classes will assume that an {@link Activity} + * is dispatching all of the required events to the class. This flag should + * only be used internally or if you are creating your own base activity + * modeled after one of the included types (e.g., {@code SherlockActivity}). + */ + public static final int FLAG_DELEGATE = 1; + + + /** + * Register an ActionBarSherlock implementation. + * + * @param implementationClass Target implementation class which extends + * {@link ActionBarSherlock}. This class must also be annotated with + * {@link Implementation}. + */ + public static void registerImplementation(Class implementationClass) { + if (!implementationClass.isAnnotationPresent(Implementation.class)) { + throw new IllegalArgumentException("Class " + implementationClass.getSimpleName() + " is not annotated with @Implementation"); + } else if (IMPLEMENTATIONS.containsValue(implementationClass)) { + if (DEBUG) Log.w(TAG, "Class " + implementationClass.getSimpleName() + " already registered"); + return; + } + + Implementation impl = implementationClass.getAnnotation(Implementation.class); + if (DEBUG) Log.i(TAG, "Registering " + implementationClass.getSimpleName() + " with qualifier " + impl); + IMPLEMENTATIONS.put(impl, implementationClass); + } + + /** + * Unregister an ActionBarSherlock implementation. This should be + * considered very volatile and you should only use it if you know what + * you are doing. You have been warned. + * + * @param implementationClass Target implementation class. + * @return Boolean indicating whether the class was removed. + */ + public static boolean unregisterImplementation(Class implementationClass) { + return IMPLEMENTATIONS.values().remove(implementationClass); + } + + /** + * Wrap an activity with an action bar abstraction which will enable the + * use of a custom implementation on platforms where a native version does + * not exist. + * + * @param activity Activity to wrap. + * @return Instance to interact with the action bar. + */ + public static ActionBarSherlock wrap(Activity activity) { + return wrap(activity, 0); + } + + /** + * Wrap an activity with an action bar abstraction which will enable the + * use of a custom implementation on platforms where a native version does + * not exist. + * + * @param activity Owning activity. + * @param flags Option flags to control behavior. + * @return Instance to interact with the action bar. + */ + public static ActionBarSherlock wrap(Activity activity, int flags) { + //Create a local implementation map we can modify + HashMap> impls = + new HashMap>(IMPLEMENTATIONS); + boolean hasQualfier; + + /* DPI FILTERING */ + hasQualfier = false; + for (Implementation key : impls.keySet()) { + //Only honor TVDPI as a specific qualifier + if (key.dpi() == DisplayMetrics.DENSITY_TV) { + hasQualfier = true; + break; + } + } + if (hasQualfier) { + final boolean isTvDpi = activity.getResources().getDisplayMetrics().densityDpi == DisplayMetrics.DENSITY_TV; + for (Iterator keys = impls.keySet().iterator(); keys.hasNext(); ) { + int keyDpi = keys.next().dpi(); + if ((isTvDpi && keyDpi != DisplayMetrics.DENSITY_TV) + || (!isTvDpi && keyDpi == DisplayMetrics.DENSITY_TV)) { + keys.remove(); + } + } + } + + /* API FILTERING */ + hasQualfier = false; + for (Implementation key : impls.keySet()) { + if (key.api() != Implementation.DEFAULT_API) { + hasQualfier = true; + break; + } + } + if (hasQualfier) { + final int runtimeApi = Build.VERSION.SDK_INT; + int bestApi = 0; + for (Iterator keys = impls.keySet().iterator(); keys.hasNext(); ) { + int keyApi = keys.next().api(); + if (keyApi > runtimeApi) { + keys.remove(); + } else if (keyApi > bestApi) { + bestApi = keyApi; + } + } + for (Iterator keys = impls.keySet().iterator(); keys.hasNext(); ) { + if (keys.next().api() != bestApi) { + keys.remove(); + } + } + } + + if (impls.size() > 1) { + throw new IllegalStateException("More than one implementation matches configuration."); + } + if (impls.isEmpty()) { + throw new IllegalStateException("No implementations match configuration."); + } + Class impl = impls.values().iterator().next(); + if (DEBUG) Log.i(TAG, "Using implementation: " + impl.getSimpleName()); + + try { + Constructor ctor = impl.getConstructor(CONSTRUCTOR_ARGS); + return ctor.newInstance(activity, flags); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + } + + + /** Activity which is displaying the action bar. Also used for context. */ + protected final Activity mActivity; + /** Whether delegating actions for the activity or managing ourselves. */ + protected final boolean mIsDelegate; + + /** Reference to our custom menu inflater which supports action items. */ + protected MenuInflater mMenuInflater; + + + + protected ActionBarSherlock(Activity activity, int flags) { + if (DEBUG) Log.d(TAG, "[] activity: " + activity + ", flags: " + flags); + + mActivity = activity; + mIsDelegate = (flags & FLAG_DELEGATE) != 0; + } + + + /** + * Get the current action bar instance. + * + * @return Action bar instance. + */ + public abstract ActionBar getActionBar(); + + + /////////////////////////////////////////////////////////////////////////// + // Lifecycle and interaction callbacks when delegating + /////////////////////////////////////////////////////////////////////////// + + /** + * Notify action bar of a configuration change event. Should be dispatched + * after the call to the superclass implementation. + * + *
+     * @Override
+     * public void onConfigurationChanged(Configuration newConfig) {
+     *     super.onConfigurationChanged(newConfig);
+     *     mSherlock.dispatchConfigurationChanged(newConfig);
+     * }
+     * 
+ * + * @param newConfig The new device configuration. + */ + public void dispatchConfigurationChanged(Configuration newConfig) {} + + /** + * Notify the action bar that the activity has finished its resuming. This + * should be dispatched after the call to the superclass implementation. + * + *
+     * @Override
+     * protected void onPostResume() {
+     *     super.onPostResume();
+     *     mSherlock.dispatchPostResume();
+     * }
+     * 
+ */ + public void dispatchPostResume() {} + + /** + * Notify the action bar that the activity is pausing. This should be + * dispatched before the call to the superclass implementation. + * + *
+     * @Override
+     * protected void onPause() {
+     *     mSherlock.dispatchPause();
+     *     super.onPause();
+     * }
+     * 
+ */ + public void dispatchPause() {} + + /** + * Notify the action bar that the activity is stopping. This should be + * called before the superclass implementation. + * + *

+ * @Override + * protected void onStop() { + * mSherlock.dispatchStop(); + * super.onStop(); + * } + *

+ */ + public void dispatchStop() {} + + /** + * Indicate that the menu should be recreated by calling + * {@link OnCreateOptionsMenuListener#onCreateOptionsMenu(com.actionbarsherlock.view.Menu)}. + */ + public abstract void dispatchInvalidateOptionsMenu(); + + /** + * Notify the action bar that it should display its overflow menu if it is + * appropriate for the device. The implementation should conditionally + * call the superclass method only if this method returns {@code false}. + * + *

+ * @Override + * public void openOptionsMenu() { + * if (!mSherlock.dispatchOpenOptionsMenu()) { + * super.openOptionsMenu(); + * } + * } + *

+ * + * @return {@code true} if the opening of the menu was handled internally. + */ + public boolean dispatchOpenOptionsMenu() { + return false; + } + + /** + * Notify the action bar that it should close its overflow menu if it is + * appropriate for the device. This implementation should conditionally + * call the superclass method only if this method returns {@code false}. + * + *
+     * @Override
+     * public void closeOptionsMenu() {
+     *     if (!mSherlock.dispatchCloseOptionsMenu()) {
+     *         super.closeOptionsMenu();
+     *     }
+     * }
+     * 
+ * + * @return {@code true} if the closing of the menu was handled internally. + */ + public boolean dispatchCloseOptionsMenu() { + return false; + } + + /** + * Notify the class that the activity has finished its creation. This + * should be called after the superclass implementation. + * + *
+     * @Override
+     * protected void onPostCreate(Bundle savedInstanceState) {
+     *     mSherlock.dispatchPostCreate(savedInstanceState);
+     *     super.onPostCreate(savedInstanceState);
+     * }
+     * 
+ * + * @param savedInstanceState If the activity is being re-initialized after + * previously being shut down then this Bundle + * contains the data it most recently supplied in + * {@link Activity#}onSaveInstanceState(Bundle)}. + * Note: Otherwise it is null. + */ + public void dispatchPostCreate(Bundle savedInstanceState) {} + + /** + * Notify the action bar that the title has changed and the action bar + * should be updated to reflect the change. This should be called before + * the superclass implementation. + * + *
+     *  @Override
+     *  protected void onTitleChanged(CharSequence title, int color) {
+     *      mSherlock.dispatchTitleChanged(title, color);
+     *      super.onTitleChanged(title, color);
+     *  }
+     * 
+ * + * @param title New activity title. + * @param color New activity color. + */ + public void dispatchTitleChanged(CharSequence title, int color) {} + + /** + * Notify the action bar the user has created a key event. This is used to + * toggle the display of the overflow action item with the menu key and to + * close the action mode or expanded action item with the back key. + * + *
+     * @Override
+     * public boolean dispatchKeyEvent(KeyEvent event) {
+     *     if (mSherlock.dispatchKeyEvent(event)) {
+     *         return true;
+     *     }
+     *     return super.dispatchKeyEvent(event);
+     * }
+     * 
+ * + * @param event Description of the key event. + * @return {@code true} if the event was handled. + */ + public boolean dispatchKeyEvent(KeyEvent event) { + return false; + } + + /** + * Notify the action bar that the Activity has triggered a menu creation + * which should happen on the conclusion of {@link Activity#onCreate}. This + * will be used to gain a reference to the native menu for native and + * overflow binding as well as to indicate when compatibility create should + * occur for the first time. + * + * @param menu Activity native menu. + * @return {@code true} since we always want to say that we have a native + */ + public abstract boolean dispatchCreateOptionsMenu(android.view.Menu menu); + + /** + * Notify the action bar that the Activity has triggered a menu preparation + * which usually means that the user has requested the overflow menu via a + * hardware menu key. You should return the result of this method call and + * not call the superclass implementation. + * + *

+ * @Override + * public final boolean onPrepareOptionsMenu(android.view.Menu menu) { + * return mSherlock.dispatchPrepareOptionsMenu(menu); + * } + *

+ * + * @param menu Activity native menu. + * @return {@code true} if menu display should proceed. + */ + public abstract boolean dispatchPrepareOptionsMenu(android.view.Menu menu); + + /** + * Notify the action bar that a native options menu item has been selected. + * The implementation should return the result of this method call. + * + *

+ * @Override + * public final boolean onOptionsItemSelected(android.view.MenuItem item) { + * return mSherlock.dispatchOptionsItemSelected(item); + * } + *

+ * + * @param item Options menu item. + * @return @{code true} if the selection was handled. + */ + public abstract boolean dispatchOptionsItemSelected(android.view.MenuItem item); + + /** + * Notify the action bar that the overflow menu has been opened. The + * implementation should conditionally return {@code true} if this method + * returns {@code true}, otherwise return the result of the superclass + * method. + * + *

+ * @Override + * public final boolean onMenuOpened(int featureId, android.view.Menu menu) { + * if (mSherlock.dispatchMenuOpened(featureId, menu)) { + * return true; + * } + * return super.onMenuOpened(featureId, menu); + * } + *

+ * + * @param featureId Window feature which triggered the event. + * @param menu Activity native menu. + * @return {@code true} if the event was handled by this method. + */ + public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) { + return false; + } + + /** + * Notify the action bar that the overflow menu has been closed. This + * method should be called before the superclass implementation. + * + *

+ * @Override + * public void onPanelClosed(int featureId, android.view.Menu menu) { + * mSherlock.dispatchPanelClosed(featureId, menu); + * super.onPanelClosed(featureId, menu); + * } + *

+ * + * @param featureId + * @param menu + */ + public void dispatchPanelClosed(int featureId, android.view.Menu menu) {} + + /** + * Notify the action bar that the activity has been destroyed. This method + * should be called before the superclass implementation. + * + *

+ * @Override + * public void onDestroy() { + * mSherlock.dispatchDestroy(); + * super.onDestroy(); + * } + *

+ */ + public void dispatchDestroy() {} + + public void dispatchSaveInstanceState(Bundle outState) {} + + public void dispatchRestoreInstanceState(Bundle savedInstanceState) {} + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * Internal method to trigger the menu creation process. + * + * @return {@code true} if menu creation should proceed. + */ + protected final boolean callbackCreateOptionsMenu(Menu menu) { + if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] menu: " + menu); + + boolean result = true; + if (mActivity instanceof OnCreatePanelMenuListener) { + OnCreatePanelMenuListener listener = (OnCreatePanelMenuListener)mActivity; + result = listener.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu); + } else if (mActivity instanceof OnCreateOptionsMenuListener) { + OnCreateOptionsMenuListener listener = (OnCreateOptionsMenuListener)mActivity; + result = listener.onCreateOptionsMenu(menu); + } + + if (DEBUG) Log.d(TAG, "[callbackCreateOptionsMenu] returning " + result); + return result; + } + + /** + * Internal method to trigger the menu preparation process. + * + * @return {@code true} if menu preparation should proceed. + */ + protected final boolean callbackPrepareOptionsMenu(Menu menu) { + if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] menu: " + menu); + + boolean result = true; + if (mActivity instanceof OnPreparePanelListener) { + OnPreparePanelListener listener = (OnPreparePanelListener)mActivity; + result = listener.onPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu); + } else if (mActivity instanceof OnPrepareOptionsMenuListener) { + OnPrepareOptionsMenuListener listener = (OnPrepareOptionsMenuListener)mActivity; + result = listener.onPrepareOptionsMenu(menu); + } + + if (DEBUG) Log.d(TAG, "[callbackPrepareOptionsMenu] returning " + result); + return result; + } + + /** + * Internal method for dispatching options menu selection to the owning + * activity callback. + * + * @param item Selected options menu item. + * @return {@code true} if the item selection was handled in the callback. + */ + protected final boolean callbackOptionsItemSelected(MenuItem item) { + if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] item: " + item.getTitleCondensed()); + + boolean result = false; + if (mActivity instanceof OnMenuItemSelectedListener) { + OnMenuItemSelectedListener listener = (OnMenuItemSelectedListener)mActivity; + result = listener.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item); + } else if (mActivity instanceof OnOptionsItemSelectedListener) { + OnOptionsItemSelectedListener listener = (OnOptionsItemSelectedListener)mActivity; + result = listener.onOptionsItemSelected(item); + } + + if (DEBUG) Log.d(TAG, "[callbackOptionsItemSelected] returning " + result); + return result; + } + + + /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + + + /** + * Query for the availability of a certain feature. + * + * @param featureId The feature ID to check. + * @return {@code true} if feature is enabled, {@code false} otherwise. + */ + public abstract boolean hasFeature(int featureId); + + /** + * Enable extended screen features. This must be called before + * {@code setContentView()}. May be called as many times as desired as long + * as it is before {@code setContentView()}. If not called, no extended + * features will be available. You can not turn off a feature once it is + * requested. + * + * @param featureId The desired features, defined as constants by Window. + * @return Returns true if the requested feature is supported and now + * enabled. + */ + public abstract boolean requestFeature(int featureId); + + /** + * Set extra options that will influence the UI for this window. + * + * @param uiOptions Flags specifying extra options for this window. + */ + public abstract void setUiOptions(int uiOptions); + + /** + * Set extra options that will influence the UI for this window. Only the + * bits filtered by mask will be modified. + * + * @param uiOptions Flags specifying extra options for this window. + * @param mask Flags specifying which options should be modified. Others + * will remain unchanged. + */ + public abstract void setUiOptions(int uiOptions, int mask); + + /** + * Set the content of the activity inside the action bar. + * + * @param layoutResId Layout resource ID. + */ + public abstract void setContentView(int layoutResId); + + /** + * Set the content of the activity inside the action bar. + * + * @param view The desired content to display. + */ + public void setContentView(View view) { + if (DEBUG) Log.d(TAG, "[setContentView] view: " + view); + + setContentView(view, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); + } + + /** + * Set the content of the activity inside the action bar. + * + * @param view The desired content to display. + * @param params Layout parameters to apply to the view. + */ + public abstract void setContentView(View view, ViewGroup.LayoutParams params); + + /** + * Variation on {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)} + * to add an additional content view to the screen. Added after any + * existing ones on the screen -- existing views are NOT removed. + * + * @param view The desired content to display. + * @param params Layout parameters for the view. + */ + public abstract void addContentView(View view, ViewGroup.LayoutParams params); + + /** + * Change the title associated with this activity. + */ + public abstract void setTitle(CharSequence title); + + /** + * Change the title associated with this activity. + */ + public void setTitle(int resId) { + if (DEBUG) Log.d(TAG, "[setTitle] resId: " + resId); + + setTitle(mActivity.getString(resId)); + } + + /** + * Sets the visibility of the progress bar in the title. + *

+ * In order for the progress bar to be shown, the feature must be requested + * via {@link #requestWindowFeature(int)}. + * + * @param visible Whether to show the progress bars in the title. + */ + public abstract void setProgressBarVisibility(boolean visible); + + /** + * Sets the visibility of the indeterminate progress bar in the title. + *

+ * In order for the progress bar to be shown, the feature must be requested + * via {@link #requestWindowFeature(int)}. + * + * @param visible Whether to show the progress bars in the title. + */ + public abstract void setProgressBarIndeterminateVisibility(boolean visible); + + /** + * Sets whether the horizontal progress bar in the title should be indeterminate (the circular + * is always indeterminate). + *

+ * In order for the progress bar to be shown, the feature must be requested + * via {@link #requestWindowFeature(int)}. + * + * @param indeterminate Whether the horizontal progress bar should be indeterminate. + */ + public abstract void setProgressBarIndeterminate(boolean indeterminate); + + /** + * Sets the progress for the progress bars in the title. + *

+ * In order for the progress bar to be shown, the feature must be requested + * via {@link #requestWindowFeature(int)}. + * + * @param progress The progress for the progress bar. Valid ranges are from + * 0 to 10000 (both inclusive). If 10000 is given, the progress + * bar will be completely filled and will fade out. + */ + public abstract void setProgress(int progress); + + /** + * Sets the secondary progress for the progress bar in the title. This + * progress is drawn between the primary progress (set via + * {@link #setProgress(int)} and the background. It can be ideal for media + * scenarios such as showing the buffering progress while the default + * progress shows the play progress. + *

+ * In order for the progress bar to be shown, the feature must be requested + * via {@link #requestWindowFeature(int)}. + * + * @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from + * 0 to 10000 (both inclusive). + */ + public abstract void setSecondaryProgress(int secondaryProgress); + + /** + * Get a menu inflater instance which supports the newer menu attributes. + * + * @return Menu inflater instance. + */ + public MenuInflater getMenuInflater() { + if (DEBUG) Log.d(TAG, "[getMenuInflater]"); + + // Make sure that action views can get an appropriate theme. + if (mMenuInflater == null) { + if (getActionBar() != null) { + mMenuInflater = new MenuInflater(getThemedContext(), mActivity); + } else { + mMenuInflater = new MenuInflater(mActivity); + } + } + return mMenuInflater; + } + + protected abstract Context getThemedContext(); + + /** + * Start an action mode. + * + * @param callback Callback that will manage lifecycle events for this + * context mode. + * @return The ContextMode that was started, or null if it was canceled. + * @see ActionMode + */ + public abstract ActionMode startActionMode(ActionMode.Callback callback); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java new file mode 100644 index 000000000..03755be2b --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/ActionBar.java @@ -0,0 +1,956 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.app; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.support.v4.app.FragmentTransaction; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewDebug; +import android.view.ViewGroup; +import android.view.ViewGroup.MarginLayoutParams; +import android.widget.SpinnerAdapter; + +/** + * A window feature at the top of the activity that may display the activity title, navigation + * modes, and other interactive items. + *

Beginning with Android 3.0 (API level 11), the action bar appears at the top of an + * activity's window when the activity uses the system's {@link + * android.R.style#Theme_Holo Holo} theme (or one of its descendant themes), which is the default. + * You may otherwise add the action bar by calling {@link + * android.view.Window#requestFeature requestFeature(FEATURE_ACTION_BAR)} or by declaring it in a + * custom theme with the {@link android.R.styleable#Theme_windowActionBar windowActionBar} property. + *

By default, the action bar shows the application icon on + * the left, followed by the activity title. If your activity has an options menu, you can make + * select items accessible directly from the action bar as "action items". You can also + * modify various characteristics of the action bar or remove it completely.

+ *

From your activity, you can retrieve an instance of {@link ActionBar} by calling {@link + * android.app.Activity#getActionBar getActionBar()}.

+ *

In some cases, the action bar may be overlayed by another bar that enables contextual actions, + * using an {@link android.view.ActionMode}. For example, when the user selects one or more items in + * your activity, you can enable an action mode that offers actions specific to the selected + * items, with a UI that temporarily replaces the action bar. Although the UI may occupy the + * same space, the {@link android.view.ActionMode} APIs are distinct and independent from those for + * {@link ActionBar}. + *

+ *

Developer Guides

+ *

For information about how to use the action bar, including how to add action items, navigation + * modes and more, read the Action + * Bar developer guide.

+ *
+ */ +public abstract class ActionBar { + /** + * Standard navigation mode. Consists of either a logo or icon + * and title text with an optional subtitle. Clicking any of these elements + * will dispatch onOptionsItemSelected to the host Activity with + * a MenuItem with item ID android.R.id.home. + */ + public static final int NAVIGATION_MODE_STANDARD = android.app.ActionBar.NAVIGATION_MODE_STANDARD; + + /** + * List navigation mode. Instead of static title text this mode + * presents a list menu for navigation within the activity. + * e.g. this might be presented to the user as a dropdown list. + */ + public static final int NAVIGATION_MODE_LIST = android.app.ActionBar.NAVIGATION_MODE_LIST; + + /** + * Tab navigation mode. Instead of static title text this mode + * presents a series of tabs for navigation within the activity. + */ + public static final int NAVIGATION_MODE_TABS = android.app.ActionBar.NAVIGATION_MODE_TABS; + + /** + * Use logo instead of icon if available. This flag will cause appropriate + * navigation modes to use a wider logo in place of the standard icon. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public static final int DISPLAY_USE_LOGO = android.app.ActionBar.DISPLAY_USE_LOGO; + + /** + * Show 'home' elements in this action bar, leaving more space for other + * navigation elements. This includes logo and icon. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public static final int DISPLAY_SHOW_HOME = android.app.ActionBar.DISPLAY_SHOW_HOME; + + /** + * Display the 'home' element such that it appears as an 'up' affordance. + * e.g. show an arrow to the left indicating the action that will be taken. + * + * Set this flag if selecting the 'home' button in the action bar to return + * up by a single level in your UI rather than back to the top level or front page. + * + *

Setting this option will implicitly enable interaction with the home/up + * button. See {@link #setHomeButtonEnabled(boolean)}. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public static final int DISPLAY_HOME_AS_UP = android.app.ActionBar.DISPLAY_HOME_AS_UP; + + /** + * Show the activity title and subtitle, if present. + * + * @see #setTitle(CharSequence) + * @see #setTitle(int) + * @see #setSubtitle(CharSequence) + * @see #setSubtitle(int) + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public static final int DISPLAY_SHOW_TITLE = android.app.ActionBar.DISPLAY_SHOW_TITLE; + + /** + * Show the custom view if one has been set. + * @see #setCustomView(View) + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public static final int DISPLAY_SHOW_CUSTOM = android.app.ActionBar.DISPLAY_SHOW_CUSTOM; + + /** + * Set the action bar into custom navigation mode, supplying a view + * for custom navigation. + * + * Custom navigation views appear between the application icon and + * any action buttons and may use any space available there. Common + * use cases for custom navigation views might include an auto-suggesting + * address bar for a browser or other navigation mechanisms that do not + * translate well to provided navigation modes. + * + * @param view Custom navigation view to place in the ActionBar. + */ + public abstract void setCustomView(View view); + + /** + * Set the action bar into custom navigation mode, supplying a view + * for custom navigation. + * + *

Custom navigation views appear between the application icon and + * any action buttons and may use any space available there. Common + * use cases for custom navigation views might include an auto-suggesting + * address bar for a browser or other navigation mechanisms that do not + * translate well to provided navigation modes.

+ * + *

The display option {@link #DISPLAY_SHOW_CUSTOM} must be set for + * the custom view to be displayed.

+ * + * @param view Custom navigation view to place in the ActionBar. + * @param layoutParams How this custom view should layout in the bar. + * + * @see #setDisplayOptions(int, int) + */ + public abstract void setCustomView(View view, LayoutParams layoutParams); + + /** + * Set the action bar into custom navigation mode, supplying a view + * for custom navigation. + * + *

Custom navigation views appear between the application icon and + * any action buttons and may use any space available there. Common + * use cases for custom navigation views might include an auto-suggesting + * address bar for a browser or other navigation mechanisms that do not + * translate well to provided navigation modes.

+ * + *

The display option {@link #DISPLAY_SHOW_CUSTOM} must be set for + * the custom view to be displayed.

+ * + * @param resId Resource ID of a layout to inflate into the ActionBar. + * + * @see #setDisplayOptions(int, int) + */ + public abstract void setCustomView(int resId); + + /** + * Set the icon to display in the 'home' section of the action bar. + * The action bar will use an icon specified by its style or the + * activity icon by default. + * + * Whether the home section shows an icon or logo is controlled + * by the display option {@link #DISPLAY_USE_LOGO}. + * + * @param resId Resource ID of a drawable to show as an icon. + * + * @see #setDisplayUseLogoEnabled(boolean) + * @see #setDisplayShowHomeEnabled(boolean) + */ + public abstract void setIcon(int resId); + + /** + * Set the icon to display in the 'home' section of the action bar. + * The action bar will use an icon specified by its style or the + * activity icon by default. + * + * Whether the home section shows an icon or logo is controlled + * by the display option {@link #DISPLAY_USE_LOGO}. + * + * @param icon Drawable to show as an icon. + * + * @see #setDisplayUseLogoEnabled(boolean) + * @see #setDisplayShowHomeEnabled(boolean) + */ + public abstract void setIcon(Drawable icon); + + /** + * Set the logo to display in the 'home' section of the action bar. + * The action bar will use a logo specified by its style or the + * activity logo by default. + * + * Whether the home section shows an icon or logo is controlled + * by the display option {@link #DISPLAY_USE_LOGO}. + * + * @param resId Resource ID of a drawable to show as a logo. + * + * @see #setDisplayUseLogoEnabled(boolean) + * @see #setDisplayShowHomeEnabled(boolean) + */ + public abstract void setLogo(int resId); + + /** + * Set the logo to display in the 'home' section of the action bar. + * The action bar will use a logo specified by its style or the + * activity logo by default. + * + * Whether the home section shows an icon or logo is controlled + * by the display option {@link #DISPLAY_USE_LOGO}. + * + * @param logo Drawable to show as a logo. + * + * @see #setDisplayUseLogoEnabled(boolean) + * @see #setDisplayShowHomeEnabled(boolean) + */ + public abstract void setLogo(Drawable logo); + + /** + * Set the adapter and navigation callback for list navigation mode. + * + * The supplied adapter will provide views for the expanded list as well as + * the currently selected item. (These may be displayed differently.) + * + * The supplied OnNavigationListener will alert the application when the user + * changes the current list selection. + * + * @param adapter An adapter that will provide views both to display + * the current navigation selection and populate views + * within the dropdown navigation menu. + * @param callback An OnNavigationListener that will receive events when the user + * selects a navigation item. + */ + public abstract void setListNavigationCallbacks(SpinnerAdapter adapter, + OnNavigationListener callback); + + /** + * Set the selected navigation item in list or tabbed navigation modes. + * + * @param position Position of the item to select. + */ + public abstract void setSelectedNavigationItem(int position); + + /** + * Get the position of the selected navigation item in list or tabbed navigation modes. + * + * @return Position of the selected item. + */ + public abstract int getSelectedNavigationIndex(); + + /** + * Get the number of navigation items present in the current navigation mode. + * + * @return Number of navigation items. + */ + public abstract int getNavigationItemCount(); + + /** + * Set the action bar's title. This will only be displayed if + * {@link #DISPLAY_SHOW_TITLE} is set. + * + * @param title Title to set + * + * @see #setTitle(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setTitle(CharSequence title); + + /** + * Set the action bar's title. This will only be displayed if + * {@link #DISPLAY_SHOW_TITLE} is set. + * + * @param resId Resource ID of title string to set + * + * @see #setTitle(CharSequence) + * @see #setDisplayOptions(int, int) + */ + public abstract void setTitle(int resId); + + /** + * Set the action bar's subtitle. This will only be displayed if + * {@link #DISPLAY_SHOW_TITLE} is set. Set to null to disable the + * subtitle entirely. + * + * @param subtitle Subtitle to set + * + * @see #setSubtitle(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setSubtitle(CharSequence subtitle); + + /** + * Set the action bar's subtitle. This will only be displayed if + * {@link #DISPLAY_SHOW_TITLE} is set. + * + * @param resId Resource ID of subtitle string to set + * + * @see #setSubtitle(CharSequence) + * @see #setDisplayOptions(int, int) + */ + public abstract void setSubtitle(int resId); + + /** + * Set display options. This changes all display option bits at once. To change + * a limited subset of display options, see {@link #setDisplayOptions(int, int)}. + * + * @param options A combination of the bits defined by the DISPLAY_ constants + * defined in ActionBar. + */ + public abstract void setDisplayOptions(int options); + + /** + * Set selected display options. Only the options specified by mask will be changed. + * To change all display option bits at once, see {@link #setDisplayOptions(int)}. + * + *

Example: setDisplayOptions(0, DISPLAY_SHOW_HOME) will disable the + * {@link #DISPLAY_SHOW_HOME} option. + * setDisplayOptions(DISPLAY_SHOW_HOME, DISPLAY_SHOW_HOME | DISPLAY_USE_LOGO) + * will enable {@link #DISPLAY_SHOW_HOME} and disable {@link #DISPLAY_USE_LOGO}. + * + * @param options A combination of the bits defined by the DISPLAY_ constants + * defined in ActionBar. + * @param mask A bit mask declaring which display options should be changed. + */ + public abstract void setDisplayOptions(int options, int mask); + + /** + * Set whether to display the activity logo rather than the activity icon. + * A logo is often a wider, more detailed image. + * + *

To set several display options at once, see the setDisplayOptions methods. + * + * @param useLogo true to use the activity logo, false to use the activity icon. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setDisplayUseLogoEnabled(boolean useLogo); + + /** + * Set whether to include the application home affordance in the action bar. + * Home is presented as either an activity icon or logo. + * + *

To set several display options at once, see the setDisplayOptions methods. + * + * @param showHome true to show home, false otherwise. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setDisplayShowHomeEnabled(boolean showHome); + + /** + * Set whether home should be displayed as an "up" affordance. + * Set this to true if selecting "home" returns up by a single level in your UI + * rather than back to the top level or front page. + * + *

To set several display options at once, see the setDisplayOptions methods. + * + * @param showHomeAsUp true to show the user that selecting home will return one + * level up rather than to the top level of the app. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setDisplayHomeAsUpEnabled(boolean showHomeAsUp); + + /** + * Set whether an activity title/subtitle should be displayed. + * + *

To set several display options at once, see the setDisplayOptions methods. + * + * @param showTitle true to display a title/subtitle if present. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setDisplayShowTitleEnabled(boolean showTitle); + + /** + * Set whether a custom view should be displayed, if set. + * + *

To set several display options at once, see the setDisplayOptions methods. + * + * @param showCustom true if the currently set custom view should be displayed, false otherwise. + * + * @see #setDisplayOptions(int) + * @see #setDisplayOptions(int, int) + */ + public abstract void setDisplayShowCustomEnabled(boolean showCustom); + + /** + * Set the ActionBar's background. This will be used for the primary + * action bar. + * + * @param d Background drawable + * @see #setStackedBackgroundDrawable(Drawable) + * @see #setSplitBackgroundDrawable(Drawable) + */ + public abstract void setBackgroundDrawable(Drawable d); + + /** + * Set the ActionBar's stacked background. This will appear + * in the second row/stacked bar on some devices and configurations. + * + * @param d Background drawable for the stacked row + */ + public void setStackedBackgroundDrawable(Drawable d) { } + + /** + * Set the ActionBar's split background. This will appear in + * the split action bar containing menu-provided action buttons + * on some devices and configurations. + *

You can enable split action bar with {@link android.R.attr#uiOptions} + * + * @param d Background drawable for the split bar + */ + public void setSplitBackgroundDrawable(Drawable d) { } + + /** + * @return The current custom view. + */ + public abstract View getCustomView(); + + /** + * Returns the current ActionBar title in standard mode. + * Returns null if {@link #getNavigationMode()} would not return + * {@link #NAVIGATION_MODE_STANDARD}. + * + * @return The current ActionBar title or null. + */ + public abstract CharSequence getTitle(); + + /** + * Returns the current ActionBar subtitle in standard mode. + * Returns null if {@link #getNavigationMode()} would not return + * {@link #NAVIGATION_MODE_STANDARD}. + * + * @return The current ActionBar subtitle or null. + */ + public abstract CharSequence getSubtitle(); + + /** + * Returns the current navigation mode. The result will be one of: + *

    + *
  • {@link #NAVIGATION_MODE_STANDARD}
  • + *
  • {@link #NAVIGATION_MODE_LIST}
  • + *
  • {@link #NAVIGATION_MODE_TABS}
  • + *
+ * + * @return The current navigation mode. + */ + public abstract int getNavigationMode(); + + /** + * Set the current navigation mode. + * + * @param mode The new mode to set. + * @see #NAVIGATION_MODE_STANDARD + * @see #NAVIGATION_MODE_LIST + * @see #NAVIGATION_MODE_TABS + */ + public abstract void setNavigationMode(int mode); + + /** + * @return The current set of display options. + */ + public abstract int getDisplayOptions(); + + /** + * Create and return a new {@link Tab}. + * This tab will not be included in the action bar until it is added. + * + *

Very often tabs will be used to switch between {@link Fragment} + * objects. Here is a typical implementation of such tabs:

+ * + * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/FragmentTabs.java + * complete} + * + * @return A new Tab + * + * @see #addTab(Tab) + */ + public abstract Tab newTab(); + + /** + * Add a tab for use in tabbed navigation mode. The tab will be added at the end of the list. + * If this is the first tab to be added it will become the selected tab. + * + * @param tab Tab to add + */ + public abstract void addTab(Tab tab); + + /** + * Add a tab for use in tabbed navigation mode. The tab will be added at the end of the list. + * + * @param tab Tab to add + * @param setSelected True if the added tab should become the selected tab. + */ + public abstract void addTab(Tab tab, boolean setSelected); + + /** + * Add a tab for use in tabbed navigation mode. The tab will be inserted at + * position. If this is the first tab to be added it will become + * the selected tab. + * + * @param tab The tab to add + * @param position The new position of the tab + */ + public abstract void addTab(Tab tab, int position); + + /** + * Add a tab for use in tabbed navigation mode. The tab will be insterted at + * position. + * + * @param tab The tab to add + * @param position The new position of the tab + * @param setSelected True if the added tab should become the selected tab. + */ + public abstract void addTab(Tab tab, int position, boolean setSelected); + + /** + * Remove a tab from the action bar. If the removed tab was selected it will be deselected + * and another tab will be selected if present. + * + * @param tab The tab to remove + */ + public abstract void removeTab(Tab tab); + + /** + * Remove a tab from the action bar. If the removed tab was selected it will be deselected + * and another tab will be selected if present. + * + * @param position Position of the tab to remove + */ + public abstract void removeTabAt(int position); + + /** + * Remove all tabs from the action bar and deselect the current tab. + */ + public abstract void removeAllTabs(); + + /** + * Select the specified tab. If it is not a child of this action bar it will be added. + * + *

Note: If you want to select by index, use {@link #setSelectedNavigationItem(int)}.

+ * + * @param tab Tab to select + */ + public abstract void selectTab(Tab tab); + + /** + * Returns the currently selected tab if in tabbed navigation mode and there is at least + * one tab present. + * + * @return The currently selected tab or null + */ + public abstract Tab getSelectedTab(); + + /** + * Returns the tab at the specified index. + * + * @param index Index value in the range 0-get + * @return + */ + public abstract Tab getTabAt(int index); + + /** + * Returns the number of tabs currently registered with the action bar. + * @return Tab count + */ + public abstract int getTabCount(); + + /** + * Retrieve the current height of the ActionBar. + * + * @return The ActionBar's height + */ + public abstract int getHeight(); + + /** + * Show the ActionBar if it is not currently showing. + * If the window hosting the ActionBar does not have the feature + * {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application + * content to fit the new space available. + */ + public abstract void show(); + + /** + * Hide the ActionBar if it is currently showing. + * If the window hosting the ActionBar does not have the feature + * {@link Window#FEATURE_ACTION_BAR_OVERLAY} it will resize application + * content to fit the new space available. + */ + public abstract void hide(); + + /** + * @return true if the ActionBar is showing, false otherwise. + */ + public abstract boolean isShowing(); + + /** + * Add a listener that will respond to menu visibility change events. + * + * @param listener The new listener to add + */ + public abstract void addOnMenuVisibilityListener(OnMenuVisibilityListener listener); + + /** + * Remove a menu visibility listener. This listener will no longer receive menu + * visibility change events. + * + * @param listener A listener to remove that was previously added + */ + public abstract void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener); + + /** + * Enable or disable the "home" button in the corner of the action bar. (Note that this + * is the application home/up affordance on the action bar, not the systemwide home + * button.) + * + *

This defaults to true for packages targeting < API 14. For packages targeting + * API 14 or greater, the application should call this method to enable interaction + * with the home/up affordance. + * + *

Setting the {@link #DISPLAY_HOME_AS_UP} display option will automatically enable + * the home button. + * + * @param enabled true to enable the home button, false to disable the home button. + */ + public void setHomeButtonEnabled(boolean enabled) { } + + /** + * Returns a {@link Context} with an appropriate theme for creating views that + * will appear in the action bar. If you are inflating or instantiating custom views + * that will appear in an action bar, you should use the Context returned by this method. + * (This includes adapters used for list navigation mode.) + * This will ensure that views contrast properly against the action bar. + * + * @return A themed Context for creating views + */ + public Context getThemedContext() { return null; } + + /** + * Listener interface for ActionBar navigation events. + */ + public interface OnNavigationListener { + /** + * This method is called whenever a navigation item in your action bar + * is selected. + * + * @param itemPosition Position of the item clicked. + * @param itemId ID of the item clicked. + * @return True if the event was handled, false otherwise. + */ + public boolean onNavigationItemSelected(int itemPosition, long itemId); + } + + /** + * Listener for receiving events when action bar menus are shown or hidden. + */ + public interface OnMenuVisibilityListener { + /** + * Called when an action bar menu is shown or hidden. Applications may want to use + * this to tune auto-hiding behavior for the action bar or pause/resume video playback, + * gameplay, or other activity within the main content area. + * + * @param isVisible True if an action bar menu is now visible, false if no action bar + * menus are visible. + */ + public void onMenuVisibilityChanged(boolean isVisible); + } + + /** + * A tab in the action bar. + * + *

Tabs manage the hiding and showing of {@link Fragment}s. + */ + public static abstract class Tab { + /** + * An invalid position for a tab. + * + * @see #getPosition() + */ + public static final int INVALID_POSITION = -1; + + /** + * Return the current position of this tab in the action bar. + * + * @return Current position, or {@link #INVALID_POSITION} if this tab is not currently in + * the action bar. + */ + public abstract int getPosition(); + + /** + * Return the icon associated with this tab. + * + * @return The tab's icon + */ + public abstract Drawable getIcon(); + + /** + * Return the text of this tab. + * + * @return The tab's text + */ + public abstract CharSequence getText(); + + /** + * Set the icon displayed on this tab. + * + * @param icon The drawable to use as an icon + * @return The current instance for call chaining + */ + public abstract Tab setIcon(Drawable icon); + + /** + * Set the icon displayed on this tab. + * + * @param resId Resource ID referring to the drawable to use as an icon + * @return The current instance for call chaining + */ + public abstract Tab setIcon(int resId); + + /** + * Set the text displayed on this tab. Text may be truncated if there is not + * room to display the entire string. + * + * @param text The text to display + * @return The current instance for call chaining + */ + public abstract Tab setText(CharSequence text); + + /** + * Set the text displayed on this tab. Text may be truncated if there is not + * room to display the entire string. + * + * @param resId A resource ID referring to the text that should be displayed + * @return The current instance for call chaining + */ + public abstract Tab setText(int resId); + + /** + * Set a custom view to be used for this tab. This overrides values set by + * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}. + * + * @param view Custom view to be used as a tab. + * @return The current instance for call chaining + */ + public abstract Tab setCustomView(View view); + + /** + * Set a custom view to be used for this tab. This overrides values set by + * {@link #setText(CharSequence)} and {@link #setIcon(Drawable)}. + * + * @param layoutResId A layout resource to inflate and use as a custom tab view + * @return The current instance for call chaining + */ + public abstract Tab setCustomView(int layoutResId); + + /** + * Retrieve a previously set custom view for this tab. + * + * @return The custom view set by {@link #setCustomView(View)}. + */ + public abstract View getCustomView(); + + /** + * Give this Tab an arbitrary object to hold for later use. + * + * @param obj Object to store + * @return The current instance for call chaining + */ + public abstract Tab setTag(Object obj); + + /** + * @return This Tab's tag object. + */ + public abstract Object getTag(); + + /** + * Set the {@link TabListener} that will handle switching to and from this tab. + * All tabs must have a TabListener set before being added to the ActionBar. + * + * @param listener Listener to handle tab selection events + * @return The current instance for call chaining + */ + public abstract Tab setTabListener(TabListener listener); + + /** + * Select this tab. Only valid if the tab has been added to the action bar. + */ + public abstract void select(); + + /** + * Set a description of this tab's content for use in accessibility support. + * If no content description is provided the title will be used. + * + * @param resId A resource ID referring to the description text + * @return The current instance for call chaining + * @see #setContentDescription(CharSequence) + * @see #getContentDescription() + */ + public abstract Tab setContentDescription(int resId); + + /** + * Set a description of this tab's content for use in accessibility support. + * If no content description is provided the title will be used. + * + * @param contentDesc Description of this tab's content + * @return The current instance for call chaining + * @see #setContentDescription(int) + * @see #getContentDescription() + */ + public abstract Tab setContentDescription(CharSequence contentDesc); + + /** + * Gets a brief description of this tab's content for use in accessibility support. + * + * @return Description of this tab's content + * @see #setContentDescription(CharSequence) + * @see #setContentDescription(int) + */ + public abstract CharSequence getContentDescription(); + } + + /** + * Callback interface invoked when a tab is focused, unfocused, added, or removed. + */ + public interface TabListener { + /** + * Called when a tab enters the selected state. + * + * @param tab The tab that was selected + * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute + * during a tab switch. The previous tab's unselect and this tab's select will be + * executed in a single transaction. This FragmentTransaction does not support + * being added to the back stack. + */ + public void onTabSelected(Tab tab, FragmentTransaction ft); + + /** + * Called when a tab exits the selected state. + * + * @param tab The tab that was unselected + * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute + * during a tab switch. This tab's unselect and the newly selected tab's select + * will be executed in a single transaction. This FragmentTransaction does not + * support being added to the back stack. + */ + public void onTabUnselected(Tab tab, FragmentTransaction ft); + + /** + * Called when a tab that is already selected is chosen again by the user. + * Some applications may use this action to return to the top level of a category. + * + * @param tab The tab that was reselected. + * @param ft A {@link FragmentTransaction} for queuing fragment operations to execute + * once this method returns. This FragmentTransaction does not support + * being added to the back stack. + */ + public void onTabReselected(Tab tab, FragmentTransaction ft); + } + + /** + * Per-child layout information associated with action bar custom views. + * + * @attr ref android.R.styleable#ActionBar_LayoutParams_layout_gravity + */ + public static class LayoutParams extends MarginLayoutParams { + private static final int[] ATTRS = new int[] { + android.R.attr.layout_gravity + }; + + /** + * Gravity for the view associated with these LayoutParams. + * + * @see android.view.Gravity + */ + @ViewDebug.ExportedProperty(mapping = { + @ViewDebug.IntToString(from = -1, to = "NONE"), + @ViewDebug.IntToString(from = Gravity.NO_GRAVITY, to = "NONE"), + @ViewDebug.IntToString(from = Gravity.TOP, to = "TOP"), + @ViewDebug.IntToString(from = Gravity.BOTTOM, to = "BOTTOM"), + @ViewDebug.IntToString(from = Gravity.LEFT, to = "LEFT"), + @ViewDebug.IntToString(from = Gravity.RIGHT, to = "RIGHT"), + @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL, to = "CENTER_VERTICAL"), + @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL, to = "FILL_VERTICAL"), + @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"), + @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL, to = "FILL_HORIZONTAL"), + @ViewDebug.IntToString(from = Gravity.CENTER, to = "CENTER"), + @ViewDebug.IntToString(from = Gravity.FILL, to = "FILL") + }) + public int gravity = -1; + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + + TypedArray a = c.obtainStyledAttributes(attrs, ATTRS); + gravity = a.getInt(0, -1); + a.recycle(); + } + + public LayoutParams(int width, int height) { + super(width, height); + this.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT; + } + + public LayoutParams(int width, int height, int gravity) { + super(width, height); + this.gravity = gravity; + } + + public LayoutParams(int gravity) { + this(WRAP_CONTENT, FILL_PARENT, gravity); + } + + public LayoutParams(LayoutParams source) { + super(source); + + this.gravity = source.gravity; + } + + public LayoutParams(ViewGroup.LayoutParams source) { + super(source); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java new file mode 100644 index 000000000..7b4543640 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockActivity.java @@ -0,0 +1,270 @@ +package com.actionbarsherlock.app; + +import android.app.Activity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; +import android.view.ViewGroup.LayoutParams; +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; +import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; +import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; +import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockActivity extends Activity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + private ActionBarSherlock mSherlock; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); + } + return mSherlock; + } + + + /////////////////////////////////////////////////////////////////////////// + // Action bar and mode + /////////////////////////////////////////////////////////////////////////// + + public ActionBar getSupportActionBar() { + return getSherlock().getActionBar(); + } + + public ActionMode startActionMode(ActionMode.Callback callback) { + return getSherlock().startActionMode(callback); + } + + @Override + public void onActionModeStarted(ActionMode mode) {} + + @Override + public void onActionModeFinished(ActionMode mode) {} + + + /////////////////////////////////////////////////////////////////////////// + // General lifecycle/callback dispatching + /////////////////////////////////////////////////////////////////////////// + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getSherlock().dispatchConfigurationChanged(newConfig); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getSherlock().dispatchPostResume(); + } + + @Override + protected void onPause() { + getSherlock().dispatchPause(); + super.onPause(); + } + + @Override + protected void onStop() { + getSherlock().dispatchStop(); + super.onStop(); + } + + @Override + protected void onDestroy() { + getSherlock().dispatchDestroy(); + super.onDestroy(); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + getSherlock().dispatchPostCreate(savedInstanceState); + super.onPostCreate(savedInstanceState); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + getSherlock().dispatchTitleChanged(title, color); + super.onTitleChanged(title, color); + } + + @Override + public final boolean onMenuOpened(int featureId, android.view.Menu menu) { + if (getSherlock().dispatchMenuOpened(featureId, menu)) { + return true; + } + return super.onMenuOpened(featureId, menu); + } + + @Override + public void onPanelClosed(int featureId, android.view.Menu menu) { + getSherlock().dispatchPanelClosed(featureId, menu); + super.onPanelClosed(featureId, menu); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (getSherlock().dispatchKeyEvent(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + getSherlock().dispatchSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + getSherlock().dispatchRestoreInstanceState(savedInstanceState); + } + + /////////////////////////////////////////////////////////////////////////// + // Native menu handling + /////////////////////////////////////////////////////////////////////////// + + public MenuInflater getSupportMenuInflater() { + return getSherlock().getMenuInflater(); + } + + public void invalidateOptionsMenu() { + getSherlock().dispatchInvalidateOptionsMenu(); + } + + public void supportInvalidateOptionsMenu() { + invalidateOptionsMenu(); + } + + @Override + public final boolean onCreateOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchCreateOptionsMenu(menu); + } + + @Override + public final boolean onPrepareOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchPrepareOptionsMenu(menu); + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return getSherlock().dispatchOptionsItemSelected(item); + } + + @Override + public void openOptionsMenu() { + if (!getSherlock().dispatchOpenOptionsMenu()) { + super.openOptionsMenu(); + } + } + + @Override + public void closeOptionsMenu() { + if (!getSherlock().dispatchCloseOptionsMenu()) { + super.closeOptionsMenu(); + } + } + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onCreateOptionsMenu(menu); + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onPrepareOptionsMenu(menu); + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onOptionsItemSelected(item); + } + return false; + } + + public boolean onOptionsItemSelected(MenuItem item) { + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // Content + /////////////////////////////////////////////////////////////////////////// + + @Override + public void addContentView(View view, LayoutParams params) { + getSherlock().addContentView(view, params); + } + + @Override + public void setContentView(int layoutResId) { + getSherlock().setContentView(layoutResId); + } + + @Override + public void setContentView(View view, LayoutParams params) { + getSherlock().setContentView(view, params); + } + + @Override + public void setContentView(View view) { + getSherlock().setContentView(view); + } + + public void requestWindowFeature(long featureId) { + getSherlock().requestFeature((int)featureId); + } + + + /////////////////////////////////////////////////////////////////////////// + // Progress Indication + /////////////////////////////////////////////////////////////////////////// + + public void setSupportProgress(int progress) { + getSherlock().setProgress(progress); + } + + public void setSupportProgressBarIndeterminate(boolean indeterminate) { + getSherlock().setProgressBarIndeterminate(indeterminate); + } + + public void setSupportProgressBarIndeterminateVisibility(boolean visible) { + getSherlock().setProgressBarIndeterminateVisibility(visible); + } + + public void setSupportProgressBarVisibility(boolean visible) { + getSherlock().setProgressBarVisibility(visible); + } + + public void setSupportSecondaryProgress(int secondaryProgress) { + getSherlock().setSecondaryProgress(secondaryProgress); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java new file mode 100644 index 000000000..a7c856bf0 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockDialogFragment.java @@ -0,0 +1,68 @@ +package com.actionbarsherlock.app; + +import android.app.Activity; +import android.support.v4.app.DialogFragment; +import com.actionbarsherlock.internal.view.menu.MenuItemWrapper; +import com.actionbarsherlock.internal.view.menu.MenuWrapper; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnCreateOptionsMenuListener; +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnOptionsItemSelectedListener; +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnPrepareOptionsMenuListener; + +public class SherlockDialogFragment extends DialogFragment implements OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener, OnOptionsItemSelectedListener { + private SherlockFragmentActivity mActivity; + + public SherlockFragmentActivity getSherlockActivity() { + return mActivity; + } + + @Override + public void onAttach(Activity activity) { + if (!(activity instanceof SherlockFragmentActivity)) { + throw new IllegalStateException(getClass().getSimpleName() + " must be attached to a SherlockFragmentActivity."); + } + mActivity = (SherlockFragmentActivity)activity; + + super.onAttach(activity); + } + + @Override + public void onDetach() { + mActivity = null; + super.onDetach(); + } + + @Override + public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { + onCreateOptionsMenu(new MenuWrapper(menu), mActivity.getSupportMenuInflater()); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + //Nothing to see here. + } + + @Override + public final void onPrepareOptionsMenu(android.view.Menu menu) { + onPrepareOptionsMenu(new MenuWrapper(menu)); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + //Nothing to see here. + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return onOptionsItemSelected(new MenuItemWrapper(item)); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + //Nothing to see here. + return false; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java new file mode 100644 index 000000000..078f9b0ca --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockExpandableListActivity.java @@ -0,0 +1,259 @@ +package com.actionbarsherlock.app; + +import android.app.ExpandableListActivity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; +import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; +import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; +import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockExpandableListActivity extends ExpandableListActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + private ActionBarSherlock mSherlock; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); + } + return mSherlock; + } + + + /////////////////////////////////////////////////////////////////////////// + // Action bar and mode + /////////////////////////////////////////////////////////////////////////// + + public ActionBar getSupportActionBar() { + return getSherlock().getActionBar(); + } + + public ActionMode startActionMode(ActionMode.Callback callback) { + return getSherlock().startActionMode(callback); + } + + @Override + public void onActionModeStarted(ActionMode mode) {} + + @Override + public void onActionModeFinished(ActionMode mode) {} + + + /////////////////////////////////////////////////////////////////////////// + // General lifecycle/callback dispatching + /////////////////////////////////////////////////////////////////////////// + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getSherlock().dispatchConfigurationChanged(newConfig); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getSherlock().dispatchPostResume(); + } + + @Override + protected void onPause() { + getSherlock().dispatchPause(); + super.onPause(); + } + + @Override + protected void onStop() { + getSherlock().dispatchStop(); + super.onStop(); + } + + @Override + protected void onDestroy() { + getSherlock().dispatchDestroy(); + super.onDestroy(); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + getSherlock().dispatchPostCreate(savedInstanceState); + super.onPostCreate(savedInstanceState); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + getSherlock().dispatchTitleChanged(title, color); + super.onTitleChanged(title, color); + } + + @Override + public final boolean onMenuOpened(int featureId, android.view.Menu menu) { + if (getSherlock().dispatchMenuOpened(featureId, menu)) { + return true; + } + return super.onMenuOpened(featureId, menu); + } + + @Override + public void onPanelClosed(int featureId, android.view.Menu menu) { + getSherlock().dispatchPanelClosed(featureId, menu); + super.onPanelClosed(featureId, menu); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (getSherlock().dispatchKeyEvent(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } + + + /////////////////////////////////////////////////////////////////////////// + // Native menu handling + /////////////////////////////////////////////////////////////////////////// + + public MenuInflater getSupportMenuInflater() { + return getSherlock().getMenuInflater(); + } + + public void invalidateOptionsMenu() { + getSherlock().dispatchInvalidateOptionsMenu(); + } + + public void supportInvalidateOptionsMenu() { + invalidateOptionsMenu(); + } + + @Override + public final boolean onCreateOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchCreateOptionsMenu(menu); + } + + @Override + public final boolean onPrepareOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchPrepareOptionsMenu(menu); + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return getSherlock().dispatchOptionsItemSelected(item); + } + + @Override + public void openOptionsMenu() { + if (!getSherlock().dispatchOpenOptionsMenu()) { + super.openOptionsMenu(); + } + } + + @Override + public void closeOptionsMenu() { + if (!getSherlock().dispatchCloseOptionsMenu()) { + super.closeOptionsMenu(); + } + } + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onCreateOptionsMenu(menu); + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onPrepareOptionsMenu(menu); + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onOptionsItemSelected(item); + } + return false; + } + + public boolean onOptionsItemSelected(MenuItem item) { + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // Content + /////////////////////////////////////////////////////////////////////////// + + @Override + public void addContentView(View view, LayoutParams params) { + getSherlock().addContentView(view, params); + } + + @Override + public void setContentView(int layoutResId) { + getSherlock().setContentView(layoutResId); + } + + @Override + public void setContentView(View view, LayoutParams params) { + getSherlock().setContentView(view, params); + } + + @Override + public void setContentView(View view) { + getSherlock().setContentView(view); + } + + public void requestWindowFeature(long featureId) { + getSherlock().requestFeature((int)featureId); + } + + + /////////////////////////////////////////////////////////////////////////// + // Progress Indication + /////////////////////////////////////////////////////////////////////////// + + public void setSupportProgress(int progress) { + getSherlock().setProgress(progress); + } + + public void setSupportProgressBarIndeterminate(boolean indeterminate) { + getSherlock().setProgressBarIndeterminate(indeterminate); + } + + public void setSupportProgressBarIndeterminateVisibility(boolean visible) { + getSherlock().setProgressBarIndeterminateVisibility(visible); + } + + public void setSupportProgressBarVisibility(boolean visible) { + getSherlock().setProgressBarVisibility(visible); + } + + public void setSupportSecondaryProgress(int secondaryProgress) { + getSherlock().setSecondaryProgress(secondaryProgress); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java new file mode 100644 index 000000000..0f24e9c85 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragment.java @@ -0,0 +1,68 @@ +package com.actionbarsherlock.app; + +import android.app.Activity; +import android.support.v4.app.Fragment; +import com.actionbarsherlock.internal.view.menu.MenuItemWrapper; +import com.actionbarsherlock.internal.view.menu.MenuWrapper; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnCreateOptionsMenuListener; +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnOptionsItemSelectedListener; +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnPrepareOptionsMenuListener; + +public class SherlockFragment extends Fragment implements OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener, OnOptionsItemSelectedListener { + private SherlockFragmentActivity mActivity; + + public SherlockFragmentActivity getSherlockActivity() { + return mActivity; + } + + @Override + public void onAttach(Activity activity) { + if (!(activity instanceof SherlockFragmentActivity)) { + throw new IllegalStateException(getClass().getSimpleName() + " must be attached to a SherlockFragmentActivity."); + } + mActivity = (SherlockFragmentActivity)activity; + + super.onAttach(activity); + } + + @Override + public void onDetach() { + mActivity = null; + super.onDetach(); + } + + @Override + public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { + onCreateOptionsMenu(new MenuWrapper(menu), mActivity.getSupportMenuInflater()); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + //Nothing to see here. + } + + @Override + public final void onPrepareOptionsMenu(android.view.Menu menu) { + onPrepareOptionsMenu(new MenuWrapper(menu)); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + //Nothing to see here. + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return onOptionsItemSelected(new MenuItemWrapper(item)); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + //Nothing to see here. + return false; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java new file mode 100644 index 000000000..3d092f033 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockFragmentActivity.java @@ -0,0 +1,303 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.v4.app.Watson; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +import static com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; +import static com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; + +/** @see {@link android.support.v4.app.Watson} */ +public class SherlockFragmentActivity extends Watson implements OnActionModeStartedListener, OnActionModeFinishedListener { + private static final boolean DEBUG = false; + private static final String TAG = "SherlockFragmentActivity"; + + private ActionBarSherlock mSherlock; + private boolean mIgnoreNativeCreate = false; + private boolean mIgnoreNativePrepare = false; + private boolean mIgnoreNativeSelected = false; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); + } + return mSherlock; + } + + + /////////////////////////////////////////////////////////////////////////// + // Action bar and mode + /////////////////////////////////////////////////////////////////////////// + + public ActionBar getSupportActionBar() { + return getSherlock().getActionBar(); + } + + public ActionMode startActionMode(ActionMode.Callback callback) { + return getSherlock().startActionMode(callback); + } + + @Override + public void onActionModeStarted(ActionMode mode) {} + + @Override + public void onActionModeFinished(ActionMode mode) {} + + + /////////////////////////////////////////////////////////////////////////// + // General lifecycle/callback dispatching + /////////////////////////////////////////////////////////////////////////// + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getSherlock().dispatchConfigurationChanged(newConfig); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getSherlock().dispatchPostResume(); + } + + @Override + protected void onPause() { + getSherlock().dispatchPause(); + super.onPause(); + } + + @Override + protected void onStop() { + getSherlock().dispatchStop(); + super.onStop(); + } + + @Override + protected void onDestroy() { + getSherlock().dispatchDestroy(); + super.onDestroy(); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + getSherlock().dispatchPostCreate(savedInstanceState); + super.onPostCreate(savedInstanceState); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + getSherlock().dispatchTitleChanged(title, color); + super.onTitleChanged(title, color); + } + + @Override + public final boolean onMenuOpened(int featureId, android.view.Menu menu) { + if (getSherlock().dispatchMenuOpened(featureId, menu)) { + return true; + } + return super.onMenuOpened(featureId, menu); + } + + @Override + public void onPanelClosed(int featureId, android.view.Menu menu) { + getSherlock().dispatchPanelClosed(featureId, menu); + super.onPanelClosed(featureId, menu); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (getSherlock().dispatchKeyEvent(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + getSherlock().dispatchSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + getSherlock().dispatchRestoreInstanceState(savedInstanceState); + } + + /////////////////////////////////////////////////////////////////////////// + // Native menu handling + /////////////////////////////////////////////////////////////////////////// + + public MenuInflater getSupportMenuInflater() { + if (DEBUG) Log.d(TAG, "[getSupportMenuInflater]"); + + return getSherlock().getMenuInflater(); + } + + public void invalidateOptionsMenu() { + if (DEBUG) Log.d(TAG, "[invalidateOptionsMenu]"); + + getSherlock().dispatchInvalidateOptionsMenu(); + } + + public void supportInvalidateOptionsMenu() { + if (DEBUG) Log.d(TAG, "[supportInvalidateOptionsMenu]"); + + invalidateOptionsMenu(); + } + + @Override + public final boolean onCreatePanelMenu(int featureId, android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] featureId: " + featureId + ", menu: " + menu); + + if (featureId == Window.FEATURE_OPTIONS_PANEL && !mIgnoreNativeCreate) { + mIgnoreNativeCreate = true; + boolean result = getSherlock().dispatchCreateOptionsMenu(menu); + mIgnoreNativeCreate = false; + + if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] returning " + result); + return result; + } + return super.onCreatePanelMenu(featureId, menu); + } + + @Override + public final boolean onCreateOptionsMenu(android.view.Menu menu) { + return true; + } + + @Override + public final boolean onPreparePanel(int featureId, View view, android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[onPreparePanel] featureId: " + featureId + ", view: " + view + ", menu: " + menu); + + if (featureId == Window.FEATURE_OPTIONS_PANEL && !mIgnoreNativePrepare) { + mIgnoreNativePrepare = true; + boolean result = getSherlock().dispatchPrepareOptionsMenu(menu); + mIgnoreNativePrepare = false; + + if (DEBUG) Log.d(TAG, "[onPreparePanel] returning " + result); + return result; + } + return super.onPreparePanel(featureId, view, menu); + } + + @Override + public final boolean onPrepareOptionsMenu(android.view.Menu menu) { + return true; + } + + @Override + public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) { + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] featureId: " + featureId + ", item: " + item); + + if (featureId == Window.FEATURE_OPTIONS_PANEL && !mIgnoreNativeSelected) { + mIgnoreNativeSelected = true; + boolean result = getSherlock().dispatchOptionsItemSelected(item); + mIgnoreNativeSelected = false; + + if (DEBUG) Log.d(TAG, "[onMenuItemSelected] returning " + result); + return result; + } + return super.onMenuItemSelected(featureId, item); + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return false; + } + + @Override + public void openOptionsMenu() { + if (!getSherlock().dispatchOpenOptionsMenu()) { + super.openOptionsMenu(); + } + } + + @Override + public void closeOptionsMenu() { + if (!getSherlock().dispatchCloseOptionsMenu()) { + super.closeOptionsMenu(); + } + } + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + public boolean onOptionsItemSelected(MenuItem item) { + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // Content + /////////////////////////////////////////////////////////////////////////// + + @Override + public void addContentView(View view, LayoutParams params) { + getSherlock().addContentView(view, params); + } + + @Override + public void setContentView(int layoutResId) { + getSherlock().setContentView(layoutResId); + } + + @Override + public void setContentView(View view, LayoutParams params) { + getSherlock().setContentView(view, params); + } + + @Override + public void setContentView(View view) { + getSherlock().setContentView(view); + } + + public void requestWindowFeature(long featureId) { + getSherlock().requestFeature((int)featureId); + } + + + /////////////////////////////////////////////////////////////////////////// + // Progress Indication + /////////////////////////////////////////////////////////////////////////// + + public void setSupportProgress(int progress) { + getSherlock().setProgress(progress); + } + + public void setSupportProgressBarIndeterminate(boolean indeterminate) { + getSherlock().setProgressBarIndeterminate(indeterminate); + } + + public void setSupportProgressBarIndeterminateVisibility(boolean visible) { + getSherlock().setProgressBarIndeterminateVisibility(visible); + } + + public void setSupportProgressBarVisibility(boolean visible) { + getSherlock().setProgressBarVisibility(visible); + } + + public void setSupportSecondaryProgress(int secondaryProgress) { + getSherlock().setSecondaryProgress(secondaryProgress); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java new file mode 100644 index 000000000..aba6d85e8 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListActivity.java @@ -0,0 +1,270 @@ +package com.actionbarsherlock.app; + +import android.app.ListActivity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; +import android.view.ViewGroup.LayoutParams; +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; +import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; +import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; +import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockListActivity extends ListActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + private ActionBarSherlock mSherlock; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); + } + return mSherlock; + } + + + /////////////////////////////////////////////////////////////////////////// + // Action bar and mode + /////////////////////////////////////////////////////////////////////////// + + public ActionBar getSupportActionBar() { + return getSherlock().getActionBar(); + } + + public ActionMode startActionMode(ActionMode.Callback callback) { + return getSherlock().startActionMode(callback); + } + + @Override + public void onActionModeStarted(ActionMode mode) {} + + @Override + public void onActionModeFinished(ActionMode mode) {} + + + /////////////////////////////////////////////////////////////////////////// + // General lifecycle/callback dispatching + /////////////////////////////////////////////////////////////////////////// + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getSherlock().dispatchConfigurationChanged(newConfig); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getSherlock().dispatchPostResume(); + } + + @Override + protected void onPause() { + getSherlock().dispatchPause(); + super.onPause(); + } + + @Override + protected void onStop() { + getSherlock().dispatchStop(); + super.onStop(); + } + + @Override + protected void onDestroy() { + getSherlock().dispatchDestroy(); + super.onDestroy(); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + getSherlock().dispatchPostCreate(savedInstanceState); + super.onPostCreate(savedInstanceState); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + getSherlock().dispatchTitleChanged(title, color); + super.onTitleChanged(title, color); + } + + @Override + public final boolean onMenuOpened(int featureId, android.view.Menu menu) { + if (getSherlock().dispatchMenuOpened(featureId, menu)) { + return true; + } + return super.onMenuOpened(featureId, menu); + } + + @Override + public void onPanelClosed(int featureId, android.view.Menu menu) { + getSherlock().dispatchPanelClosed(featureId, menu); + super.onPanelClosed(featureId, menu); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (getSherlock().dispatchKeyEvent(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + getSherlock().dispatchSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + getSherlock().dispatchRestoreInstanceState(savedInstanceState); + } + + /////////////////////////////////////////////////////////////////////////// + // Native menu handling + /////////////////////////////////////////////////////////////////////////// + + public MenuInflater getSupportMenuInflater() { + return getSherlock().getMenuInflater(); + } + + public void invalidateOptionsMenu() { + getSherlock().dispatchInvalidateOptionsMenu(); + } + + public void supportInvalidateOptionsMenu() { + invalidateOptionsMenu(); + } + + @Override + public final boolean onCreateOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchCreateOptionsMenu(menu); + } + + @Override + public final boolean onPrepareOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchPrepareOptionsMenu(menu); + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return getSherlock().dispatchOptionsItemSelected(item); + } + + @Override + public void openOptionsMenu() { + if (!getSherlock().dispatchOpenOptionsMenu()) { + super.openOptionsMenu(); + } + } + + @Override + public void closeOptionsMenu() { + if (!getSherlock().dispatchCloseOptionsMenu()) { + super.closeOptionsMenu(); + } + } + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onCreateOptionsMenu(menu); + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onPrepareOptionsMenu(menu); + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onOptionsItemSelected(item); + } + return false; + } + + public boolean onOptionsItemSelected(MenuItem item) { + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // Content + /////////////////////////////////////////////////////////////////////////// + + @Override + public void addContentView(View view, LayoutParams params) { + getSherlock().addContentView(view, params); + } + + @Override + public void setContentView(int layoutResId) { + getSherlock().setContentView(layoutResId); + } + + @Override + public void setContentView(View view, LayoutParams params) { + getSherlock().setContentView(view, params); + } + + @Override + public void setContentView(View view) { + getSherlock().setContentView(view); + } + + public void requestWindowFeature(long featureId) { + getSherlock().requestFeature((int)featureId); + } + + + /////////////////////////////////////////////////////////////////////////// + // Progress Indication + /////////////////////////////////////////////////////////////////////////// + + public void setSupportProgress(int progress) { + getSherlock().setProgress(progress); + } + + public void setSupportProgressBarIndeterminate(boolean indeterminate) { + getSherlock().setProgressBarIndeterminate(indeterminate); + } + + public void setSupportProgressBarIndeterminateVisibility(boolean visible) { + getSherlock().setProgressBarIndeterminateVisibility(visible); + } + + public void setSupportProgressBarVisibility(boolean visible) { + getSherlock().setProgressBarVisibility(visible); + } + + public void setSupportSecondaryProgress(int secondaryProgress) { + getSherlock().setSecondaryProgress(secondaryProgress); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java new file mode 100644 index 000000000..13ca3c49f --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockListFragment.java @@ -0,0 +1,68 @@ +package com.actionbarsherlock.app; + +import android.app.Activity; +import android.support.v4.app.ListFragment; +import com.actionbarsherlock.internal.view.menu.MenuItemWrapper; +import com.actionbarsherlock.internal.view.menu.MenuWrapper; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnCreateOptionsMenuListener; +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnOptionsItemSelectedListener; +import static com.actionbarsherlock.app.SherlockFragmentActivity.OnPrepareOptionsMenuListener; + +public class SherlockListFragment extends ListFragment implements OnCreateOptionsMenuListener, OnPrepareOptionsMenuListener, OnOptionsItemSelectedListener { + private SherlockFragmentActivity mActivity; + + public SherlockFragmentActivity getSherlockActivity() { + return mActivity; + } + + @Override + public void onAttach(Activity activity) { + if (!(activity instanceof SherlockFragmentActivity)) { + throw new IllegalStateException(getClass().getSimpleName() + " must be attached to a SherlockFragmentActivity."); + } + mActivity = (SherlockFragmentActivity)activity; + + super.onAttach(activity); + } + + @Override + public void onDetach() { + mActivity = null; + super.onDetach(); + } + + @Override + public final void onCreateOptionsMenu(android.view.Menu menu, android.view.MenuInflater inflater) { + onCreateOptionsMenu(new MenuWrapper(menu), mActivity.getSupportMenuInflater()); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + //Nothing to see here. + } + + @Override + public final void onPrepareOptionsMenu(android.view.Menu menu) { + onPrepareOptionsMenu(new MenuWrapper(menu)); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + //Nothing to see here. + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return onOptionsItemSelected(new MenuItemWrapper(item)); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + //Nothing to see here. + return false; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java new file mode 100644 index 000000000..bee72cb25 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/app/SherlockPreferenceActivity.java @@ -0,0 +1,270 @@ +package com.actionbarsherlock.app; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.view.Window; +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeFinishedListener; +import com.actionbarsherlock.ActionBarSherlock.OnActionModeStartedListener; +import com.actionbarsherlock.ActionBarSherlock.OnCreatePanelMenuListener; +import com.actionbarsherlock.ActionBarSherlock.OnMenuItemSelectedListener; +import com.actionbarsherlock.ActionBarSherlock.OnPreparePanelListener; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public abstract class SherlockPreferenceActivity extends PreferenceActivity implements OnCreatePanelMenuListener, OnPreparePanelListener, OnMenuItemSelectedListener, OnActionModeStartedListener, OnActionModeFinishedListener { + private ActionBarSherlock mSherlock; + + protected final ActionBarSherlock getSherlock() { + if (mSherlock == null) { + mSherlock = ActionBarSherlock.wrap(this, ActionBarSherlock.FLAG_DELEGATE); + } + return mSherlock; + } + + + /////////////////////////////////////////////////////////////////////////// + // Action bar and mode + /////////////////////////////////////////////////////////////////////////// + + public ActionBar getSupportActionBar() { + return getSherlock().getActionBar(); + } + + public ActionMode startActionMode(ActionMode.Callback callback) { + return getSherlock().startActionMode(callback); + } + + @Override + public void onActionModeStarted(ActionMode mode) {} + + @Override + public void onActionModeFinished(ActionMode mode) {} + + + /////////////////////////////////////////////////////////////////////////// + // General lifecycle/callback dispatching + /////////////////////////////////////////////////////////////////////////// + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getSherlock().dispatchConfigurationChanged(newConfig); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getSherlock().dispatchPostResume(); + } + + @Override + protected void onPause() { + getSherlock().dispatchPause(); + super.onPause(); + } + + @Override + protected void onStop() { + getSherlock().dispatchStop(); + super.onStop(); + } + + @Override + protected void onDestroy() { + getSherlock().dispatchDestroy(); + super.onDestroy(); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + getSherlock().dispatchPostCreate(savedInstanceState); + super.onPostCreate(savedInstanceState); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + getSherlock().dispatchTitleChanged(title, color); + super.onTitleChanged(title, color); + } + + @Override + public final boolean onMenuOpened(int featureId, android.view.Menu menu) { + if (getSherlock().dispatchMenuOpened(featureId, menu)) { + return true; + } + return super.onMenuOpened(featureId, menu); + } + + @Override + public void onPanelClosed(int featureId, android.view.Menu menu) { + getSherlock().dispatchPanelClosed(featureId, menu); + super.onPanelClosed(featureId, menu); + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (getSherlock().dispatchKeyEvent(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + getSherlock().dispatchSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + getSherlock().dispatchRestoreInstanceState(savedInstanceState); + } + + /////////////////////////////////////////////////////////////////////////// + // Native menu handling + /////////////////////////////////////////////////////////////////////////// + + public MenuInflater getSupportMenuInflater() { + return getSherlock().getMenuInflater(); + } + + public void invalidateOptionsMenu() { + getSherlock().dispatchInvalidateOptionsMenu(); + } + + public void supportInvalidateOptionsMenu() { + invalidateOptionsMenu(); + } + + @Override + public final boolean onCreateOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchCreateOptionsMenu(menu); + } + + @Override + public final boolean onPrepareOptionsMenu(android.view.Menu menu) { + return getSherlock().dispatchPrepareOptionsMenu(menu); + } + + @Override + public final boolean onOptionsItemSelected(android.view.MenuItem item) { + return getSherlock().dispatchOptionsItemSelected(item); + } + + @Override + public void openOptionsMenu() { + if (!getSherlock().dispatchOpenOptionsMenu()) { + super.openOptionsMenu(); + } + } + + @Override + public void closeOptionsMenu() { + if (!getSherlock().dispatchCloseOptionsMenu()) { + super.closeOptionsMenu(); + } + } + + + /////////////////////////////////////////////////////////////////////////// + // Sherlock menu handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public boolean onCreatePanelMenu(int featureId, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onCreateOptionsMenu(menu); + } + return false; + } + + public boolean onCreateOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onPreparePanel(int featureId, View view, Menu menu) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onPrepareOptionsMenu(menu); + } + return false; + } + + public boolean onPrepareOptionsMenu(Menu menu) { + return true; + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + if (featureId == Window.FEATURE_OPTIONS_PANEL) { + return onOptionsItemSelected(item); + } + return false; + } + + public boolean onOptionsItemSelected(MenuItem item) { + return false; + } + + + /////////////////////////////////////////////////////////////////////////// + // Content + /////////////////////////////////////////////////////////////////////////// + + @Override + public void addContentView(View view, LayoutParams params) { + getSherlock().addContentView(view, params); + } + + @Override + public void setContentView(int layoutResId) { + getSherlock().setContentView(layoutResId); + } + + @Override + public void setContentView(View view, LayoutParams params) { + getSherlock().setContentView(view, params); + } + + @Override + public void setContentView(View view) { + getSherlock().setContentView(view); + } + + public void requestWindowFeature(long featureId) { + getSherlock().requestFeature((int)featureId); + } + + + /////////////////////////////////////////////////////////////////////////// + // Progress Indication + /////////////////////////////////////////////////////////////////////////// + + public void setSupportProgress(int progress) { + getSherlock().setProgress(progress); + } + + public void setSupportProgressBarIndeterminate(boolean indeterminate) { + getSherlock().setProgressBarIndeterminate(indeterminate); + } + + public void setSupportProgressBarIndeterminateVisibility(boolean visible) { + getSherlock().setProgressBarIndeterminateVisibility(visible); + } + + public void setSupportProgressBarVisibility(boolean visible) { + getSherlock().setProgressBarVisibility(visible); + } + + public void setSupportSecondaryProgress(int secondaryProgress) { + getSherlock().setSecondaryProgress(secondaryProgress); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java new file mode 100644 index 000000000..5e69275c7 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockCompat.java @@ -0,0 +1,1203 @@ +package com.actionbarsherlock.internal; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import org.xmlpull.v1.XmlPullParser; +import android.app.Activity; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.util.AndroidRuntimeException; +import android.util.Log; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewStub; +import android.view.Window; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.TextView; +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.internal.app.ActionBarImpl; +import com.actionbarsherlock.internal.view.StandaloneActionMode; +import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; +import com.actionbarsherlock.internal.view.menu.MenuBuilder; +import com.actionbarsherlock.internal.view.menu.MenuItemImpl; +import com.actionbarsherlock.internal.view.menu.MenuPresenter; +import com.actionbarsherlock.internal.widget.ActionBarContainer; +import com.actionbarsherlock.internal.widget.ActionBarContextView; +import com.actionbarsherlock.internal.widget.ActionBarView; +import com.actionbarsherlock.internal.widget.IcsProgressBar; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; + +@ActionBarSherlock.Implementation(api = 7) +public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBuilder.Callback, com.actionbarsherlock.view.Window.Callback, MenuPresenter.Callback, android.view.MenuItem.OnMenuItemClickListener { + /** Window features which are enabled by default. */ + protected static final int DEFAULT_FEATURES = 0; + + static private final String PANELS_TAG = "sherlock:Panels"; + + public ActionBarSherlockCompat(Activity activity, int flags) { + super(activity, flags); + } + + + /////////////////////////////////////////////////////////////////////////// + // Properties + /////////////////////////////////////////////////////////////////////////// + + /** Whether or not the device has a dedicated menu key button. */ + private boolean mReserveOverflow; + /** Lazy-load indicator for {@link #mReserveOverflow}. */ + private boolean mReserveOverflowSet = false; + + /** Current menu instance for managing action items. */ + private MenuBuilder mMenu; + /** Map between native options items and sherlock items. */ + protected HashMap mNativeItemMap; + + /** Parent view of the window decoration (action bar, mode, etc.). */ + private ViewGroup mDecor; + /** Parent view of the activity content. */ + private ViewGroup mContentParent; + + /** Whether or not the title is stable and can be displayed. */ + private boolean mIsTitleReady = false; + /** Whether or not the parent activity has been destroyed. */ + private boolean mIsDestroyed = false; + + /* Emulate PanelFeatureState */ + private boolean mClosingActionMenu; + private boolean mMenuIsPrepared; + private boolean mMenuRefreshContent; + private Bundle mMenuFrozenActionViewState; + + /** Implementation which backs the action bar interface API. */ + private ActionBarImpl aActionBar; + /** Main action bar view which displays the core content. */ + private ActionBarView wActionBar; + /** Relevant window and action bar features flags. */ + private int mFeatures = DEFAULT_FEATURES; + /** Relevant user interface option flags. */ + private int mUiOptions = 0; + + /** Decor indeterminate progress indicator. */ + private IcsProgressBar mCircularProgressBar; + /** Decor progress indicator. */ + private IcsProgressBar mHorizontalProgressBar; + + /** Current displayed context action bar, if any. */ + private ActionMode mActionMode; + /** Parent view in which the context action bar is displayed. */ + private ActionBarContextView mActionModeView; + + /** Title view used with dialogs. */ + private TextView mTitleView; + /** Current activity title. */ + private CharSequence mTitle = null; + /** Whether or not this "activity" is floating (i.e., a dialog) */ + private boolean mIsFloating; + + + + /////////////////////////////////////////////////////////////////////////// + // Instance methods + /////////////////////////////////////////////////////////////////////////// + + @Override + public ActionBar getActionBar() { + if (DEBUG) Log.d(TAG, "[getActionBar]"); + + initActionBar(); + return aActionBar; + } + + private void initActionBar() { + if (DEBUG) Log.d(TAG, "[initActionBar]"); + + // Initializing the window decor can change window feature flags. + // Make sure that we have the correct set before performing the test below. + if (mDecor == null) { + installDecor(); + } + + if ((aActionBar != null) || !hasFeature(Window.FEATURE_ACTION_BAR) || hasFeature(Window.FEATURE_NO_TITLE) || mActivity.isChild()) { + return; + } + + aActionBar = new ActionBarImpl(mActivity, mFeatures); + + if (!mIsDelegate) { + //We may never get another chance to set the title + wActionBar.setWindowTitle(mActivity.getTitle()); + } + } + + @Override + protected Context getThemedContext() { + return aActionBar.getThemedContext(); + } + + @Override + public void setTitle(CharSequence title) { + if (DEBUG) Log.d(TAG, "[setTitle] title: " + title); + + dispatchTitleChanged(title, 0); + } + + @Override + public ActionMode startActionMode(ActionMode.Callback callback) { + if (DEBUG) Log.d(TAG, "[startActionMode] callback: " + callback); + + if (mActionMode != null) { + mActionMode.finish(); + } + + final ActionMode.Callback wrappedCallback = new ActionModeCallbackWrapper(callback); + ActionMode mode = null; + + //Emulate Activity's onWindowStartingActionMode: + initActionBar(); + if (aActionBar != null) { + mode = aActionBar.startActionMode(wrappedCallback); + } + + if (mode != null) { + mActionMode = mode; + } else { + if (mActionModeView == null) { + ViewStub stub = (ViewStub)mDecor.findViewById(R.id.abs__action_mode_bar_stub); + if (stub != null) { + mActionModeView = (ActionBarContextView)stub.inflate(); + } + } + if (mActionModeView != null) { + mActionModeView.killMode(); + mode = new StandaloneActionMode(mActivity, mActionModeView, wrappedCallback, true); + if (callback.onCreateActionMode(mode, mode.getMenu())) { + mode.invalidate(); + mActionModeView.initForMode(mode); + mActionModeView.setVisibility(View.VISIBLE); + mActionMode = mode; + mActionModeView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + } else { + mActionMode = null; + } + } + } + if (mActionMode != null && mActivity instanceof OnActionModeStartedListener) { + ((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode); + } + return mActionMode; + } + + + /////////////////////////////////////////////////////////////////////////// + // Lifecycle and interaction callbacks for delegation + /////////////////////////////////////////////////////////////////////////// + + @Override + public void dispatchConfigurationChanged(Configuration newConfig) { + if (DEBUG) Log.d(TAG, "[dispatchConfigurationChanged] newConfig: " + newConfig); + + if (aActionBar != null) { + aActionBar.onConfigurationChanged(newConfig); + } + } + + @Override + public void dispatchPostResume() { + if (DEBUG) Log.d(TAG, "[dispatchPostResume]"); + + if (aActionBar != null) { + aActionBar.setShowHideAnimationEnabled(true); + } + } + + @Override + public void dispatchPause() { + if (DEBUG) Log.d(TAG, "[dispatchPause]"); + + if (wActionBar != null && wActionBar.isOverflowMenuShowing()) { + wActionBar.hideOverflowMenu(); + } + } + + @Override + public void dispatchStop() { + if (DEBUG) Log.d(TAG, "[dispatchStop]"); + + if (aActionBar != null) { + aActionBar.setShowHideAnimationEnabled(false); + } + } + + @Override + public void dispatchInvalidateOptionsMenu() { + if (DEBUG) Log.d(TAG, "[dispatchInvalidateOptionsMenu]"); + + Bundle savedActionViewStates = null; + if (mMenu != null) { + savedActionViewStates = new Bundle(); + mMenu.saveActionViewStates(savedActionViewStates); + if (savedActionViewStates.size() > 0) { + mMenuFrozenActionViewState = savedActionViewStates; + } + // This will be started again when the panel is prepared. + mMenu.stopDispatchingItemsChanged(); + mMenu.clear(); + } + mMenuRefreshContent = true; + + // Prepare the options panel if we have an action bar + if (wActionBar != null) { + mMenuIsPrepared = false; + preparePanel(); + } + } + + @Override + public boolean dispatchOpenOptionsMenu() { + if (DEBUG) Log.d(TAG, "[dispatchOpenOptionsMenu]"); + + if (!isReservingOverflow()) { + return false; + } + + return wActionBar.showOverflowMenu(); + } + + @Override + public boolean dispatchCloseOptionsMenu() { + if (DEBUG) Log.d(TAG, "[dispatchCloseOptionsMenu]"); + + if (!isReservingOverflow()) { + return false; + } + + if (wActionBar != null) { + return wActionBar.hideOverflowMenu(); + } + return false; + } + + @Override + public void dispatchPostCreate(Bundle savedInstanceState) { + if (DEBUG) Log.d(TAG, "[dispatchOnPostCreate]"); + + if (mIsDelegate) { + mIsTitleReady = true; + } + + if (mDecor == null) { + initActionBar(); + } + } + + @Override + public boolean dispatchCreateOptionsMenu(android.view.Menu menu) { + if (DEBUG) { + Log.d(TAG, "[dispatchCreateOptionsMenu] android.view.Menu: " + menu); + Log.d(TAG, "[dispatchCreateOptionsMenu] returning true"); + } + return true; + } + + @Override + public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] android.view.Menu: " + menu); + + if (mActionMode != null) { + return false; + } + + mMenuIsPrepared = false; + if (!preparePanel()) { + return false; + } + + if (isReservingOverflow()) { + return false; + } + + if (mNativeItemMap == null) { + mNativeItemMap = new HashMap(); + } else { + mNativeItemMap.clear(); + } + + if (mMenu == null) { + return false; + } + + boolean result = mMenu.bindNativeOverflow(menu, this, mNativeItemMap); + if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] returning " + result); + return result; + } + + @Override + public boolean dispatchOptionsItemSelected(android.view.MenuItem item) { + throw new IllegalStateException("Native callback invoked. Create a test case and report!"); + } + + @Override + public boolean dispatchMenuOpened(int featureId, android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[dispatchMenuOpened] featureId: " + featureId + ", menu: " + menu); + + if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) { + if (aActionBar != null) { + aActionBar.dispatchMenuVisibilityChanged(true); + } + return true; + } + + return false; + } + + @Override + public void dispatchPanelClosed(int featureId, android.view.Menu menu){ + if (DEBUG) Log.d(TAG, "[dispatchPanelClosed] featureId: " + featureId + ", menu: " + menu); + + if (featureId == Window.FEATURE_ACTION_BAR || featureId == Window.FEATURE_OPTIONS_PANEL) { + if (aActionBar != null) { + aActionBar.dispatchMenuVisibilityChanged(false); + } + } + } + + @Override + public void dispatchTitleChanged(CharSequence title, int color) { + if (DEBUG) Log.d(TAG, "[dispatchTitleChanged] title: " + title + ", color: " + color); + + if (!mIsDelegate || mIsTitleReady) { + if (mTitleView != null) { + mTitleView.setText(title); + } else if (wActionBar != null) { + wActionBar.setWindowTitle(title); + } + } + + mTitle = title; + } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] event: " + event); + + final int keyCode = event.getKeyCode(); + + // Not handled by the view hierarchy, does the action bar want it + // to cancel out of something special? + if (keyCode == KeyEvent.KEYCODE_BACK) { + final int action = event.getAction(); + // Back cancels action modes first. + if (mActionMode != null) { + if (action == KeyEvent.ACTION_UP) { + mActionMode.finish(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + + // Next collapse any expanded action views. + if (wActionBar != null && wActionBar.hasExpandedActionView()) { + if (action == KeyEvent.ACTION_UP) { + wActionBar.collapseActionView(); + } + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true"); + return true; + } + } + + if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false"); + return false; + } + + @Override + public void dispatchDestroy() { + mIsDestroyed = true; + } + + @Override + public void dispatchSaveInstanceState(Bundle outState) { + if (mMenu != null) { + mMenuFrozenActionViewState = new Bundle(); + mMenu.saveActionViewStates(mMenuFrozenActionViewState); + } + outState.putParcelable(PANELS_TAG, mMenuFrozenActionViewState); + } + + @Override + public void dispatchRestoreInstanceState(Bundle savedInstanceState) { + mMenuFrozenActionViewState = savedInstanceState.getParcelable(PANELS_TAG); + } + + /////////////////////////////////////////////////////////////////////////// + // Menu callback lifecycle and creation + /////////////////////////////////////////////////////////////////////////// + + private boolean preparePanel() { + // Already prepared (isPrepared will be reset to false later) + if (mMenuIsPrepared) { + return true; + } + + // Init the panel state's menu--return false if init failed + if (mMenu == null || mMenuRefreshContent) { + if (mMenu == null) { + if (!initializePanelMenu() || (mMenu == null)) { + return false; + } + } + + if (wActionBar != null) { + wActionBar.setMenu(mMenu, this); + } + + // Call callback, and return if it doesn't want to display menu. + + // Creating the panel menu will involve a lot of manipulation; + // don't dispatch change events to presenters until we're done. + mMenu.stopDispatchingItemsChanged(); + if (!callbackCreateOptionsMenu(mMenu)) { + // Ditch the menu created above + mMenu = null; + + if (wActionBar != null) { + // Don't show it in the action bar either + wActionBar.setMenu(null, this); + } + + return false; + } + + mMenuRefreshContent = false; + } + + // Callback and return if the callback does not want to show the menu + + // Preparing the panel menu can involve a lot of manipulation; + // don't dispatch change events to presenters until we're done. + mMenu.stopDispatchingItemsChanged(); + + // Restore action view state before we prepare. This gives apps + // an opportunity to override frozen/restored state in onPrepare. + if (mMenuFrozenActionViewState != null) { + mMenu.restoreActionViewStates(mMenuFrozenActionViewState); + mMenuFrozenActionViewState = null; + } + + if (!callbackPrepareOptionsMenu(mMenu)) { + if (wActionBar != null) { + // The app didn't want to show the menu for now but it still exists. + // Clear it out of the action bar. + wActionBar.setMenu(null, this); + } + mMenu.startDispatchingItemsChanged(); + return false; + } + + // Set the proper keymap + KeyCharacterMap kmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); + mMenu.setQwertyMode(kmap.getKeyboardType() != KeyCharacterMap.NUMERIC); + mMenu.startDispatchingItemsChanged(); + + // Set other state + mMenuIsPrepared = true; + + return true; + } + + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { + return callbackOptionsItemSelected(item); + } + + public void onMenuModeChange(MenuBuilder menu) { + reopenMenu(true); + } + + private void reopenMenu(boolean toggleMenuMode) { + if (wActionBar != null && wActionBar.isOverflowReserved()) { + if (!wActionBar.isOverflowMenuShowing() || !toggleMenuMode) { + if (wActionBar.getVisibility() == View.VISIBLE) { + if (callbackPrepareOptionsMenu(mMenu)) { + wActionBar.showOverflowMenu(); + } + } + } else { + wActionBar.hideOverflowMenu(); + } + return; + } + } + + private boolean initializePanelMenu() { + Context context = mActivity;//getContext(); + + // If we have an action bar, initialize the menu with a context themed for it. + if (wActionBar != null) { + TypedValue outValue = new TypedValue(); + Resources.Theme currentTheme = context.getTheme(); + currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme, + outValue, true); + final int targetThemeRes = outValue.resourceId; + + if (targetThemeRes != 0 /*&& context.getThemeResId() != targetThemeRes*/) { + context = new ContextThemeWrapper(context, targetThemeRes); + } + } + + mMenu = new MenuBuilder(context); + mMenu.setCallback(this); + + return true; + } + + void checkCloseActionMenu(Menu menu) { + if (mClosingActionMenu) { + return; + } + + mClosingActionMenu = true; + wActionBar.dismissPopupMenus(); + //Callback cb = getCallback(); + //if (cb != null && !isDestroyed()) { + // cb.onPanelClosed(FEATURE_ACTION_BAR, menu); + //} + mClosingActionMenu = false; + } + + @Override + public boolean onOpenSubMenu(MenuBuilder subMenu) { + return true; + } + + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + checkCloseActionMenu(menu); + } + + @Override + public boolean onMenuItemClick(android.view.MenuItem item) { + if (DEBUG) Log.d(TAG, "[mNativeItemListener.onMenuItemClick] item: " + item); + + final MenuItemImpl sherlockItem = mNativeItemMap.get(item); + if (sherlockItem != null) { + sherlockItem.invoke(); + } else { + Log.e(TAG, "Options item \"" + item + "\" not found in mapping"); + } + + return true; //Do not allow continuation of native handling + } + + @Override + public boolean onMenuItemSelected(int featureId, MenuItem item) { + return callbackOptionsItemSelected(item); + } + + + /////////////////////////////////////////////////////////////////////////// + // Progress bar interaction and internal handling + /////////////////////////////////////////////////////////////////////////// + + @Override + public void setProgressBarVisibility(boolean visible) { + if (DEBUG) Log.d(TAG, "[setProgressBarVisibility] visible: " + visible); + + setFeatureInt(Window.FEATURE_PROGRESS, visible ? Window.PROGRESS_VISIBILITY_ON : + Window.PROGRESS_VISIBILITY_OFF); + } + + @Override + public void setProgressBarIndeterminateVisibility(boolean visible) { + if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminateVisibility] visible: " + visible); + + setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS, + visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF); + } + + @Override + public void setProgressBarIndeterminate(boolean indeterminate) { + if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminate] indeterminate: " + indeterminate); + + setFeatureInt(Window.FEATURE_PROGRESS, + indeterminate ? Window.PROGRESS_INDETERMINATE_ON : Window.PROGRESS_INDETERMINATE_OFF); + } + + @Override + public void setProgress(int progress) { + if (DEBUG) Log.d(TAG, "[setProgress] progress: " + progress); + + setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START); + } + + @Override + public void setSecondaryProgress(int secondaryProgress) { + if (DEBUG) Log.d(TAG, "[setSecondaryProgress] secondaryProgress: " + secondaryProgress); + + setFeatureInt(Window.FEATURE_PROGRESS, + secondaryProgress + Window.PROGRESS_SECONDARY_START); + } + + private void setFeatureInt(int featureId, int value) { + updateInt(featureId, value, false); + } + + private void updateInt(int featureId, int value, boolean fromResume) { + // Do nothing if the decor is not yet installed... an update will + // need to be forced when we eventually become active. + if (mContentParent == null) { + return; + } + + final int featureMask = 1 << featureId; + + if ((getFeatures() & featureMask) == 0 && !fromResume) { + return; + } + + onIntChanged(featureId, value); + } + + private void onIntChanged(int featureId, int value) { + if (featureId == Window.FEATURE_PROGRESS || featureId == Window.FEATURE_INDETERMINATE_PROGRESS) { + updateProgressBars(value); + } + } + + private void updateProgressBars(int value) { + IcsProgressBar circularProgressBar = getCircularProgressBar(true); + IcsProgressBar horizontalProgressBar = getHorizontalProgressBar(true); + + final int features = mFeatures;//getLocalFeatures(); + if (value == Window.PROGRESS_VISIBILITY_ON) { + if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) { + int level = horizontalProgressBar.getProgress(); + int visibility = (horizontalProgressBar.isIndeterminate() || level < 10000) ? + View.VISIBLE : View.INVISIBLE; + horizontalProgressBar.setVisibility(visibility); + } + if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) { + circularProgressBar.setVisibility(View.VISIBLE); + } + } else if (value == Window.PROGRESS_VISIBILITY_OFF) { + if ((features & (1 << Window.FEATURE_PROGRESS)) != 0) { + horizontalProgressBar.setVisibility(View.GONE); + } + if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0) { + circularProgressBar.setVisibility(View.GONE); + } + } else if (value == Window.PROGRESS_INDETERMINATE_ON) { + horizontalProgressBar.setIndeterminate(true); + } else if (value == Window.PROGRESS_INDETERMINATE_OFF) { + horizontalProgressBar.setIndeterminate(false); + } else if (Window.PROGRESS_START <= value && value <= Window.PROGRESS_END) { + // We want to set the progress value before testing for visibility + // so that when the progress bar becomes visible again, it has the + // correct level. + horizontalProgressBar.setProgress(value - Window.PROGRESS_START); + + if (value < Window.PROGRESS_END) { + showProgressBars(horizontalProgressBar, circularProgressBar); + } else { + hideProgressBars(horizontalProgressBar, circularProgressBar); + } + } else if (Window.PROGRESS_SECONDARY_START <= value && value <= Window.PROGRESS_SECONDARY_END) { + horizontalProgressBar.setSecondaryProgress(value - Window.PROGRESS_SECONDARY_START); + + showProgressBars(horizontalProgressBar, circularProgressBar); + } + } + + private void showProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) { + final int features = mFeatures;//getLocalFeatures(); + if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 && + spinnyProgressBar.getVisibility() == View.INVISIBLE) { + spinnyProgressBar.setVisibility(View.VISIBLE); + } + // Only show the progress bars if the primary progress is not complete + if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 && + horizontalProgressBar.getProgress() < 10000) { + horizontalProgressBar.setVisibility(View.VISIBLE); + } + } + + private void hideProgressBars(IcsProgressBar horizontalProgressBar, IcsProgressBar spinnyProgressBar) { + final int features = mFeatures;//getLocalFeatures(); + Animation anim = AnimationUtils.loadAnimation(mActivity, android.R.anim.fade_out); + anim.setDuration(1000); + if ((features & (1 << Window.FEATURE_INDETERMINATE_PROGRESS)) != 0 && + spinnyProgressBar.getVisibility() == View.VISIBLE) { + spinnyProgressBar.startAnimation(anim); + spinnyProgressBar.setVisibility(View.INVISIBLE); + } + if ((features & (1 << Window.FEATURE_PROGRESS)) != 0 && + horizontalProgressBar.getVisibility() == View.VISIBLE) { + horizontalProgressBar.startAnimation(anim); + horizontalProgressBar.setVisibility(View.INVISIBLE); + } + } + + private IcsProgressBar getCircularProgressBar(boolean shouldInstallDecor) { + if (mCircularProgressBar != null) { + return mCircularProgressBar; + } + if (mContentParent == null && shouldInstallDecor) { + installDecor(); + } + mCircularProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_circular); + if (mCircularProgressBar != null) { + mCircularProgressBar.setVisibility(View.INVISIBLE); + } + return mCircularProgressBar; + } + + private IcsProgressBar getHorizontalProgressBar(boolean shouldInstallDecor) { + if (mHorizontalProgressBar != null) { + return mHorizontalProgressBar; + } + if (mContentParent == null && shouldInstallDecor) { + installDecor(); + } + mHorizontalProgressBar = (IcsProgressBar)mDecor.findViewById(R.id.abs__progress_horizontal); + if (mHorizontalProgressBar != null) { + mHorizontalProgressBar.setVisibility(View.INVISIBLE); + } + return mHorizontalProgressBar; + } + + + /////////////////////////////////////////////////////////////////////////// + // Feature management and content interaction and creation + /////////////////////////////////////////////////////////////////////////// + + private int getFeatures() { + if (DEBUG) Log.d(TAG, "[getFeatures] returning " + mFeatures); + + return mFeatures; + } + + @Override + public boolean hasFeature(int featureId) { + if (DEBUG) Log.d(TAG, "[hasFeature] featureId: " + featureId); + + boolean result = (mFeatures & (1 << featureId)) != 0; + if (DEBUG) Log.d(TAG, "[hasFeature] returning " + result); + return result; + } + + @Override + public boolean requestFeature(int featureId) { + if (DEBUG) Log.d(TAG, "[requestFeature] featureId: " + featureId); + + if (mContentParent != null) { + throw new AndroidRuntimeException("requestFeature() must be called before adding content"); + } + + switch (featureId) { + case Window.FEATURE_ACTION_BAR: + case Window.FEATURE_ACTION_BAR_OVERLAY: + case Window.FEATURE_ACTION_MODE_OVERLAY: + case Window.FEATURE_INDETERMINATE_PROGRESS: + case Window.FEATURE_NO_TITLE: + case Window.FEATURE_PROGRESS: + mFeatures |= (1 << featureId); + return true; + + default: + return false; + } + } + + @Override + public void setUiOptions(int uiOptions) { + if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions); + + mUiOptions = uiOptions; + } + + @Override + public void setUiOptions(int uiOptions, int mask) { + if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions + ", mask: " + mask); + + mUiOptions = (mUiOptions & ~mask) | (uiOptions & mask); + } + + @Override + public void setContentView(int layoutResId) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mActivity.getLayoutInflater().inflate(layoutResId, mContentParent); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] view: " + view + ", params: " + params); + + if (mContentParent == null) { + installDecor(); + } else { + mContentParent.removeAllViews(); + } + mContentParent.addView(view, params); + + android.view.Window.Callback callback = mActivity.getWindow().getCallback(); + if (callback != null) { + callback.onContentChanged(); + } + + initActionBar(); + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + if (DEBUG) Log.d(TAG, "[addContentView] view: " + view + ", params: " + params); + + if (mContentParent == null) { + installDecor(); + } + mContentParent.addView(view, params); + + initActionBar(); + } + + private void installDecor() { + if (DEBUG) Log.d(TAG, "[installDecor]"); + + if (mDecor == null) { + mDecor = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content); + } + if (mContentParent == null) { + //Since we are not operating at the window level we need to take + //into account the fact that the true decor may have already been + //initialized and had content attached to it. If that is the case, + //copy over its children to our new content container. + List views = null; + if (mDecor.getChildCount() > 0) { + views = new ArrayList(1); //Usually there's only one child + for (int i = 0, children = mDecor.getChildCount(); i < children; i++) { + View child = mDecor.getChildAt(0); + mDecor.removeView(child); + views.add(child); + } + } + + mContentParent = generateLayout(); + + //Copy over the old children. See above for explanation. + if (views != null) { + for (View child : views) { + mContentParent.addView(child); + } + } + + mTitleView = (TextView)mDecor.findViewById(android.R.id.title); + if (mTitleView != null) { + if (hasFeature(Window.FEATURE_NO_TITLE)) { + mTitleView.setVisibility(View.GONE); + if (mContentParent instanceof FrameLayout) { + ((FrameLayout)mContentParent).setForeground(null); + } + } else { + mTitleView.setText(mTitle); + } + } else { + wActionBar = (ActionBarView)mDecor.findViewById(R.id.abs__action_bar); + if (wActionBar != null) { + wActionBar.setWindowCallback(this); + if (wActionBar.getTitle() == null) { + wActionBar.setWindowTitle(mActivity.getTitle()); + } + if (hasFeature(Window.FEATURE_PROGRESS)) { + wActionBar.initProgress(); + } + if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) { + wActionBar.initIndeterminateProgress(); + } + + //Since we don't require onCreate dispatching, parse for uiOptions here + int uiOptions = loadUiOptionsFromManifest(mActivity); + if (uiOptions != 0) { + mUiOptions = uiOptions; + } + + boolean splitActionBar = false; + final boolean splitWhenNarrow = (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0; + if (splitWhenNarrow) { + splitActionBar = getResources_getBoolean(mActivity, R.bool.abs__split_action_bar_is_narrow); + } else { + splitActionBar = mActivity.getTheme() + .obtainStyledAttributes(R.styleable.SherlockTheme) + .getBoolean(R.styleable.SherlockTheme_windowSplitActionBar, false); + } + final ActionBarContainer splitView = (ActionBarContainer)mDecor.findViewById(R.id.abs__split_action_bar); + if (splitView != null) { + wActionBar.setSplitView(splitView); + wActionBar.setSplitActionBar(splitActionBar); + wActionBar.setSplitWhenNarrow(splitWhenNarrow); + + mActionModeView = (ActionBarContextView)mDecor.findViewById(R.id.abs__action_context_bar); + mActionModeView.setSplitView(splitView); + mActionModeView.setSplitActionBar(splitActionBar); + mActionModeView.setSplitWhenNarrow(splitWhenNarrow); + } else if (splitActionBar) { + Log.e(TAG, "Requested split action bar with incompatible window decor! Ignoring request."); + } + + // Post the panel invalidate for later; avoid application onCreateOptionsMenu + // being called in the middle of onCreate or similar. + mDecor.post(new Runnable() { + @Override + public void run() { + //Invalidate if the panel menu hasn't been created before this. + if (!mIsDestroyed && !mActivity.isFinishing() && mMenu == null) { + dispatchInvalidateOptionsMenu(); + } + } + }); + } + } + } + } + + private ViewGroup generateLayout() { + if (DEBUG) Log.d(TAG, "[generateLayout]"); + + // Apply data from current theme. + + TypedArray a = mActivity.getTheme().obtainStyledAttributes(R.styleable.SherlockTheme); + + mIsFloating = a.getBoolean(R.styleable.SherlockTheme_android_windowIsFloating, false); + + if (!a.hasValue(R.styleable.SherlockTheme_windowActionBar)) { + throw new IllegalStateException("You must use Theme.Sherlock, Theme.Sherlock.Light, Theme.Sherlock.Light.DarkActionBar, or a derivative."); + } + + if (a.getBoolean(R.styleable.SherlockTheme_windowNoTitle, false)) { + requestFeature(Window.FEATURE_NO_TITLE); + } else if (a.getBoolean(R.styleable.SherlockTheme_windowActionBar, false)) { + // Don't allow an action bar if there is no title. + requestFeature(Window.FEATURE_ACTION_BAR); + } + + if (a.getBoolean(R.styleable.SherlockTheme_windowActionBarOverlay, false)) { + requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); + } + + if (a.getBoolean(R.styleable.SherlockTheme_windowActionModeOverlay, false)) { + requestFeature(Window.FEATURE_ACTION_MODE_OVERLAY); + } + + a.recycle(); + + int layoutResource; + if (!hasFeature(Window.FEATURE_NO_TITLE)) { + if (mIsFloating) { + //Trash original dialog LinearLayout + mDecor = (ViewGroup)mDecor.getParent(); + mDecor.removeAllViews(); + + layoutResource = R.layout.abs__dialog_title_holo; + } else { + if (hasFeature(Window.FEATURE_ACTION_BAR_OVERLAY)) { + layoutResource = R.layout.abs__screen_action_bar_overlay; + } else { + layoutResource = R.layout.abs__screen_action_bar; + } + } + } else if (hasFeature(Window.FEATURE_ACTION_MODE_OVERLAY) && !hasFeature(Window.FEATURE_NO_TITLE)) { + layoutResource = R.layout.abs__screen_simple_overlay_action_mode; + } else { + layoutResource = R.layout.abs__screen_simple; + } + + if (DEBUG) Log.d(TAG, "[generateLayout] using screen XML " + mActivity.getResources().getString(layoutResource)); + View in = mActivity.getLayoutInflater().inflate(layoutResource, null); + mDecor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); + + ViewGroup contentParent = (ViewGroup)mDecor.findViewById(R.id.abs__content); + if (contentParent == null) { + throw new RuntimeException("Couldn't find content container view"); + } + + //Make our new child the true content view (for fragments). VERY VOLATILE! + mDecor.setId(View.NO_ID); + contentParent.setId(android.R.id.content); + + if (hasFeature(Window.FEATURE_INDETERMINATE_PROGRESS)) { + IcsProgressBar progress = getCircularProgressBar(false); + if (progress != null) { + progress.setIndeterminate(true); + } + } + + return contentParent; + } + + + /////////////////////////////////////////////////////////////////////////// + // Miscellaneous + /////////////////////////////////////////////////////////////////////////// + + /** + * Determine whether or not the device has a dedicated menu key. + * + * @return {@code true} if native menu key is present. + */ + private boolean isReservingOverflow() { + if (!mReserveOverflowSet) { + mReserveOverflow = ActionMenuPresenter.reserveOverflow(mActivity); + mReserveOverflowSet = true; + } + return mReserveOverflow; + } + + private static int loadUiOptionsFromManifest(Activity activity) { + int uiOptions = 0; + try { + final String thisPackage = activity.getClass().getName(); + if (DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage); + + final String packageName = activity.getApplicationInfo().packageName; + final AssetManager am = activity.createPackageContext(packageName, 0).getAssets(); + final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml"); + + int eventType = xml.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + String name = xml.getName(); + + if ("application".equals(name)) { + //Check if the has the attribute + if (DEBUG) Log.d(TAG, "Got "); + + for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { + if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); + + if ("uiOptions".equals(xml.getAttributeName(i))) { + uiOptions = xml.getAttributeIntValue(i, 0); + break; //out of for loop + } + } + } else if ("activity".equals(name)) { + //Check if the is us and has the attribute + if (DEBUG) Log.d(TAG, "Got "); + Integer activityUiOptions = null; + String activityPackage = null; + boolean isOurActivity = false; + + for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { + if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); + + //We need both uiOptions and name attributes + String attrName = xml.getAttributeName(i); + if ("uiOptions".equals(attrName)) { + activityUiOptions = xml.getAttributeIntValue(i, 0); + } else if ("name".equals(attrName)) { + activityPackage = cleanActivityName(packageName, xml.getAttributeValue(i)); + if (!thisPackage.equals(activityPackage)) { + break; //out of for loop + } + isOurActivity = true; + } + + //Make sure we have both attributes before processing + if ((activityUiOptions != null) && (activityPackage != null)) { + //Our activity, uiOptions specified, override with our value + uiOptions = activityUiOptions.intValue(); + } + } + if (isOurActivity) { + //If we matched our activity but it had no logo don't + //do any more processing of the manifest + break; + } + } + } + eventType = xml.nextToken(); + } + } catch (Exception e) { + e.printStackTrace(); + } + if (DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(uiOptions)); + return uiOptions; + } + + public static String cleanActivityName(String manifestPackage, String activityName) { + if (activityName.charAt(0) == '.') { + //Relative activity name (e.g., android:name=".ui.SomeClass") + return manifestPackage + activityName; + } + if (activityName.indexOf('.', 1) == -1) { + //Unqualified activity name (e.g., android:name="SomeClass") + return manifestPackage + "." + activityName; + } + //Fully-qualified activity name (e.g., "com.my.package.SomeClass") + return activityName; + } + + /** + * Clears out internal reference when the action mode is destroyed. + */ + private class ActionModeCallbackWrapper implements ActionMode.Callback { + private final ActionMode.Callback mWrapped; + + public ActionModeCallbackWrapper(ActionMode.Callback wrapped) { + mWrapped = wrapped; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return mWrapped.onCreateActionMode(mode, menu); + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return mWrapped.onPrepareActionMode(mode, menu); + } + + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return mWrapped.onActionItemClicked(mode, item); + } + + public void onDestroyActionMode(ActionMode mode) { + mWrapped.onDestroyActionMode(mode); + if (mActionModeView != null) { + mActionModeView.setVisibility(View.GONE); + mActionModeView.removeAllViews(); + } + if (mActivity instanceof OnActionModeFinishedListener) { + ((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode); + } + mActionMode = null; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java new file mode 100644 index 000000000..0824d3848 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ActionBarSherlockNative.java @@ -0,0 +1,336 @@ +package com.actionbarsherlock.internal; + +import com.actionbarsherlock.ActionBarSherlock; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.internal.app.ActionBarWrapper; +import com.actionbarsherlock.internal.view.menu.MenuWrapper; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.MenuInflater; +import android.app.Activity; +import android.content.Context; +import android.util.Log; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.View; +import android.view.Window; +import android.view.ViewGroup.LayoutParams; + +@ActionBarSherlock.Implementation(api = 14) +public class ActionBarSherlockNative extends ActionBarSherlock { + private ActionBarWrapper mActionBar; + private ActionModeWrapper mActionMode; + private MenuWrapper mMenu; + + public ActionBarSherlockNative(Activity activity, int flags) { + super(activity, flags); + } + + + @Override + public ActionBar getActionBar() { + if (DEBUG) Log.d(TAG, "[getActionBar]"); + + initActionBar(); + return mActionBar; + } + + private void initActionBar() { + if (mActionBar != null || mActivity.getActionBar() == null) { + return; + } + + mActionBar = new ActionBarWrapper(mActivity); + } + + @Override + public void dispatchInvalidateOptionsMenu() { + if (DEBUG) Log.d(TAG, "[dispatchInvalidateOptionsMenu]"); + + mActivity.getWindow().invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL); + } + + @Override + public boolean dispatchCreateOptionsMenu(android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[dispatchCreateOptionsMenu] menu: " + menu); + + if (mMenu == null || menu != mMenu.unwrap()) { + mMenu = new MenuWrapper(menu); + } + + final boolean result = callbackCreateOptionsMenu(mMenu); + if (DEBUG) Log.d(TAG, "[dispatchCreateOptionsMenu] returning " + result); + return result; + } + + @Override + public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) { + if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] menu: " + menu); + + final boolean result = callbackPrepareOptionsMenu(mMenu); + if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] returning " + result); + return result; + } + + @Override + public boolean dispatchOptionsItemSelected(android.view.MenuItem item) { + if (DEBUG) Log.d(TAG, "[dispatchOptionsItemSelected] item: " + item.getTitleCondensed()); + + final boolean result = callbackOptionsItemSelected(mMenu.findItem(item)); + if (DEBUG) Log.d(TAG, "[dispatchOptionsItemSelected] returning " + result); + return result; + } + + @Override + public boolean hasFeature(int feature) { + if (DEBUG) Log.d(TAG, "[hasFeature] feature: " + feature); + + final boolean result = mActivity.getWindow().hasFeature(feature); + if (DEBUG) Log.d(TAG, "[hasFeature] returning " + result); + return result; + } + + @Override + public boolean requestFeature(int featureId) { + if (DEBUG) Log.d(TAG, "[requestFeature] featureId: " + featureId); + + final boolean result = mActivity.getWindow().requestFeature(featureId); + if (DEBUG) Log.d(TAG, "[requestFeature] returning " + result); + return result; + } + + @Override + public void setUiOptions(int uiOptions) { + if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions); + + mActivity.getWindow().setUiOptions(uiOptions); + } + + @Override + public void setUiOptions(int uiOptions, int mask) { + if (DEBUG) Log.d(TAG, "[setUiOptions] uiOptions: " + uiOptions + ", mask: " + mask); + + mActivity.getWindow().setUiOptions(uiOptions, mask); + } + + @Override + public void setContentView(int layoutResId) { + if (DEBUG) Log.d(TAG, "[setContentView] layoutResId: " + layoutResId); + + mActivity.getWindow().setContentView(layoutResId); + initActionBar(); + } + + @Override + public void setContentView(View view, LayoutParams params) { + if (DEBUG) Log.d(TAG, "[setContentView] view: " + view + ", params: " + params); + + mActivity.getWindow().setContentView(view, params); + initActionBar(); + } + + @Override + public void addContentView(View view, LayoutParams params) { + if (DEBUG) Log.d(TAG, "[addContentView] view: " + view + ", params: " + params); + + mActivity.getWindow().addContentView(view, params); + initActionBar(); + } + + @Override + public void setTitle(CharSequence title) { + if (DEBUG) Log.d(TAG, "[setTitle] title: " + title); + + mActivity.getWindow().setTitle(title); + } + + @Override + public void setProgressBarVisibility(boolean visible) { + if (DEBUG) Log.d(TAG, "[setProgressBarVisibility] visible: " + visible); + + mActivity.setProgressBarVisibility(visible); + } + + @Override + public void setProgressBarIndeterminateVisibility(boolean visible) { + if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminateVisibility] visible: " + visible); + + mActivity.setProgressBarIndeterminateVisibility(visible); + } + + @Override + public void setProgressBarIndeterminate(boolean indeterminate) { + if (DEBUG) Log.d(TAG, "[setProgressBarIndeterminate] indeterminate: " + indeterminate); + + mActivity.setProgressBarIndeterminate(indeterminate); + } + + @Override + public void setProgress(int progress) { + if (DEBUG) Log.d(TAG, "[setProgress] progress: " + progress); + + mActivity.setProgress(progress); + } + + @Override + public void setSecondaryProgress(int secondaryProgress) { + if (DEBUG) Log.d(TAG, "[setSecondaryProgress] secondaryProgress: " + secondaryProgress); + + mActivity.setSecondaryProgress(secondaryProgress); + } + + @Override + protected Context getThemedContext() { + Context context = mActivity; + TypedValue outValue = new TypedValue(); + mActivity.getTheme().resolveAttribute(android.R.attr.actionBarWidgetTheme, outValue, true); + if (outValue.resourceId != 0) { + //We are unable to test if this is the same as our current theme + //so we just wrap it and hope that if the attribute was specified + //then the user is intentionally specifying an alternate theme. + context = new ContextThemeWrapper(context, outValue.resourceId); + } + return context; + } + + @Override + public ActionMode startActionMode(com.actionbarsherlock.view.ActionMode.Callback callback) { + if (DEBUG) Log.d(TAG, "[startActionMode] callback: " + callback); + + if (mActionMode != null) { + mActionMode.finish(); + } + ActionModeCallbackWrapper wrapped = null; + if (callback != null) { + wrapped = new ActionModeCallbackWrapper(callback); + } + + //Calling this will trigger the callback wrapper's onCreate which + //is where we will set the new instance to mActionMode since we need + //to pass it through to the sherlock callbacks and the call below + //will not have returned yet to store its value. + if (mActivity.startActionMode(wrapped) == null) { + mActionMode = null; + } + if (mActivity instanceof OnActionModeStartedListener && mActionMode != null) { + ((OnActionModeStartedListener)mActivity).onActionModeStarted(mActionMode); + } + + return mActionMode; + } + + private class ActionModeCallbackWrapper implements android.view.ActionMode.Callback { + private final ActionMode.Callback mCallback; + + public ActionModeCallbackWrapper(ActionMode.Callback callback) { + mCallback = callback; + } + + @Override + public boolean onCreateActionMode(android.view.ActionMode mode, android.view.Menu menu) { + //See ActionBarSherlockNative#startActionMode + mActionMode = new ActionModeWrapper(mode); + + return mCallback.onCreateActionMode(mActionMode, mActionMode.getMenu()); + } + + @Override + public boolean onPrepareActionMode(android.view.ActionMode mode, android.view.Menu menu) { + return mCallback.onPrepareActionMode(mActionMode, mActionMode.getMenu()); + } + + @Override + public boolean onActionItemClicked(android.view.ActionMode mode, android.view.MenuItem item) { + return mCallback.onActionItemClicked(mActionMode, mActionMode.getMenu().findItem(item)); + } + + @Override + public void onDestroyActionMode(android.view.ActionMode mode) { + mCallback.onDestroyActionMode(mActionMode); + if (mActivity instanceof OnActionModeFinishedListener) { + ((OnActionModeFinishedListener)mActivity).onActionModeFinished(mActionMode); + } + } + } + + private class ActionModeWrapper extends ActionMode { + private final android.view.ActionMode mActionMode; + private MenuWrapper mMenu = null; + + ActionModeWrapper(android.view.ActionMode actionMode) { + mActionMode = actionMode; + } + + @Override + public void setTitle(CharSequence title) { + mActionMode.setTitle(title); + } + + @Override + public void setTitle(int resId) { + mActionMode.setTitle(resId); + } + + @Override + public void setSubtitle(CharSequence subtitle) { + mActionMode.setSubtitle(subtitle); + } + + @Override + public void setSubtitle(int resId) { + mActionMode.setSubtitle(resId); + } + + @Override + public void setCustomView(View view) { + mActionMode.setCustomView(view); + } + + @Override + public void invalidate() { + mActionMode.invalidate(); + } + + @Override + public void finish() { + mActionMode.finish(); + } + + @Override + public MenuWrapper getMenu() { + if (mMenu == null) { + mMenu = new MenuWrapper(mActionMode.getMenu()); + } + return mMenu; + } + + @Override + public CharSequence getTitle() { + return mActionMode.getTitle(); + } + + @Override + public CharSequence getSubtitle() { + return mActionMode.getSubtitle(); + } + + @Override + public View getCustomView() { + return mActionMode.getCustomView(); + } + + @Override + public MenuInflater getMenuInflater() { + return ActionBarSherlockNative.this.getMenuInflater(); + } + + @Override + public void setTag(Object tag) { + mActionMode.setTag(tag); + } + + @Override + public Object getTag() { + return mActionMode.getTag(); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java new file mode 100644 index 000000000..8e1efe8c5 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/ResourcesCompat.java @@ -0,0 +1,95 @@ +package com.actionbarsherlock.internal; + +import android.content.Context; +import android.os.Build; +import android.util.DisplayMetrics; +import com.actionbarsherlock.R; + +public final class ResourcesCompat { + //No instances + private ResourcesCompat() {} + + + /** + * Support implementation of {@code getResources().getBoolean()} that we + * can use to simulate filtering based on width and smallest width + * qualifiers on pre-3.2. + * + * @param context Context to load booleans from on 3.2+ and to fetch the + * display metrics. + * @param id Id of boolean to load. + * @return Associated boolean value as reflected by the current display + * metrics. + */ + public static boolean getResources_getBoolean(Context context, int id) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + return context.getResources().getBoolean(id); + } + + DisplayMetrics metrics = context.getResources().getDisplayMetrics(); + float widthDp = metrics.widthPixels / metrics.density; + float heightDp = metrics.heightPixels / metrics.density; + float smallestWidthDp = (widthDp < heightDp) ? widthDp : heightDp; + + if (id == R.bool.abs__action_bar_embed_tabs) { + if (widthDp >= 480) { + return true; //values-w480dp + } + return false; //values + } + if (id == R.bool.abs__split_action_bar_is_narrow) { + if (widthDp >= 480) { + return false; //values-w480dp + } + return true; //values + } + if (id == R.bool.abs__action_bar_expanded_action_views_exclusive) { + if (smallestWidthDp >= 600) { + return false; //values-sw600dp + } + return true; //values + } + if (id == R.bool.abs__config_allowActionMenuItemTextWithIcon) { + if (widthDp >= 480) { + return true; //values-w480dp + } + return false; //values + } + + throw new IllegalArgumentException("Unknown boolean resource ID " + id); + } + + /** + * Support implementation of {@code getResources().getInteger()} that we + * can use to simulate filtering based on width qualifiers on pre-3.2. + * + * @param context Context to load integers from on 3.2+ and to fetch the + * display metrics. + * @param id Id of integer to load. + * @return Associated integer value as reflected by the current display + * metrics. + */ + public static int getResources_getInteger(Context context, int id) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + return context.getResources().getInteger(id); + } + + DisplayMetrics metrics = context.getResources().getDisplayMetrics(); + float widthDp = metrics.widthPixels / metrics.density; + + if (id == R.integer.abs__max_action_buttons) { + if (widthDp >= 600) { + return 5; //values-w600dp + } + if (widthDp >= 500) { + return 4; //values-w500dp + } + if (widthDp >= 360) { + return 3; //values-w360dp + } + return 2; //values + } + + throw new IllegalArgumentException("Unknown integer resource ID " + id); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java new file mode 100644 index 000000000..d022a2465 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarImpl.java @@ -0,0 +1,1026 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.app; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Handler; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.util.TypedValue; +import android.view.ContextThemeWrapper; +import android.view.LayoutInflater; +import android.view.View; +import android.view.Window; +import android.view.accessibility.AccessibilityEvent; +import android.widget.SpinnerAdapter; +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorListenerAdapter; +import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; +import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +import com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout; +import com.actionbarsherlock.internal.view.menu.MenuBuilder; +import com.actionbarsherlock.internal.view.menu.MenuPopupHelper; +import com.actionbarsherlock.internal.view.menu.SubMenuBuilder; +import com.actionbarsherlock.internal.widget.ActionBarContainer; +import com.actionbarsherlock.internal.widget.ActionBarContextView; +import com.actionbarsherlock.internal.widget.ActionBarView; +import com.actionbarsherlock.internal.widget.ScrollingTabContainerView; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; +import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; + +/** + * ActionBarImpl is the ActionBar implementation used + * by devices of all screen sizes. If it detects a compatible decor, + * it will split contextual modes across both the ActionBarView at + * the top of the screen and a horizontal LinearLayout at the bottom + * which is normally hidden. + */ +public class ActionBarImpl extends ActionBar { + //UNUSED private static final String TAG = "ActionBarImpl"; + + private Context mContext; + private Context mThemedContext; + private Activity mActivity; + //UNUSED private Dialog mDialog; + + private ActionBarContainer mContainerView; + private ActionBarView mActionView; + private ActionBarContextView mContextView; + private ActionBarContainer mSplitView; + private NineFrameLayout mContentView; + private ScrollingTabContainerView mTabScrollView; + + private ArrayList mTabs = new ArrayList(); + + private TabImpl mSelectedTab; + private int mSavedTabPosition = INVALID_POSITION; + + ActionModeImpl mActionMode; + ActionMode mDeferredDestroyActionMode; + ActionMode.Callback mDeferredModeDestroyCallback; + + private boolean mLastMenuVisibility; + private ArrayList mMenuVisibilityListeners = + new ArrayList(); + + private static final int CONTEXT_DISPLAY_NORMAL = 0; + private static final int CONTEXT_DISPLAY_SPLIT = 1; + + private static final int INVALID_POSITION = -1; + + private int mContextDisplayMode; + private boolean mHasEmbeddedTabs; + + final Handler mHandler = new Handler(); + Runnable mTabSelector; + + private Animator mCurrentShowAnim; + private Animator mCurrentModeAnim; + private boolean mShowHideAnimationEnabled; + boolean mWasHiddenBeforeMode; + + final AnimatorListener mHideListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (mContentView != null) { + mContentView.setTranslationY(0); + mContainerView.setTranslationY(0); + } + if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { + mSplitView.setVisibility(View.GONE); + } + mContainerView.setVisibility(View.GONE); + mContainerView.setTransitioning(false); + mCurrentShowAnim = null; + completeDeferredDestroyActionMode(); + } + }; + + final AnimatorListener mShowListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mCurrentShowAnim = null; + mContainerView.requestLayout(); + } + }; + + public ActionBarImpl(Activity activity, int features) { + mActivity = activity; + Window window = activity.getWindow(); + View decor = window.getDecorView(); + init(decor); + + //window.hasFeature() workaround for pre-3.0 + if ((features & (1 << Window.FEATURE_ACTION_BAR_OVERLAY)) == 0) { + mContentView = (NineFrameLayout)decor.findViewById(android.R.id.content); + } + } + + public ActionBarImpl(Dialog dialog) { + //UNUSED mDialog = dialog; + init(dialog.getWindow().getDecorView()); + } + + private void init(View decor) { + mContext = decor.getContext(); + mActionView = (ActionBarView) decor.findViewById(R.id.abs__action_bar); + mContextView = (ActionBarContextView) decor.findViewById( + R.id.abs__action_context_bar); + mContainerView = (ActionBarContainer) decor.findViewById( + R.id.abs__action_bar_container); + mSplitView = (ActionBarContainer) decor.findViewById( + R.id.abs__split_action_bar); + + if (mActionView == null || mContextView == null || mContainerView == null) { + throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + + "with a compatible window decor layout"); + } + + mActionView.setContextView(mContextView); + mContextDisplayMode = mActionView.isSplitActionBar() ? + CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL; + + // Older apps get the home button interaction enabled by default. + // Newer apps need to enable it explicitly. + setHomeButtonEnabled(mContext.getApplicationInfo().targetSdkVersion < 14); + + setHasEmbeddedTabs(getResources_getBoolean(mContext, + R.bool.abs__action_bar_embed_tabs)); + } + + public void onConfigurationChanged(Configuration newConfig) { + setHasEmbeddedTabs(getResources_getBoolean(mContext, + R.bool.abs__action_bar_embed_tabs)); + + //Manually dispatch a configuration change to the action bar view on pre-2.2 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { + mActionView.onConfigurationChanged(newConfig); + if (mContextView != null) { + mContextView.onConfigurationChanged(newConfig); + } + } + } + + private void setHasEmbeddedTabs(boolean hasEmbeddedTabs) { + mHasEmbeddedTabs = hasEmbeddedTabs; + // Switch tab layout configuration if needed + if (!mHasEmbeddedTabs) { + mActionView.setEmbeddedTabView(null); + mContainerView.setTabContainer(mTabScrollView); + } else { + mContainerView.setTabContainer(null); + mActionView.setEmbeddedTabView(mTabScrollView); + } + final boolean isInTabMode = getNavigationMode() == NAVIGATION_MODE_TABS; + if (mTabScrollView != null) { + mTabScrollView.setVisibility(isInTabMode ? View.VISIBLE : View.GONE); + } + mActionView.setCollapsable(!mHasEmbeddedTabs && isInTabMode); + } + + private void ensureTabsExist() { + if (mTabScrollView != null) { + return; + } + + ScrollingTabContainerView tabScroller = new ScrollingTabContainerView(mContext); + + if (mHasEmbeddedTabs) { + tabScroller.setVisibility(View.VISIBLE); + mActionView.setEmbeddedTabView(tabScroller); + } else { + tabScroller.setVisibility(getNavigationMode() == NAVIGATION_MODE_TABS ? + View.VISIBLE : View.GONE); + mContainerView.setTabContainer(tabScroller); + } + mTabScrollView = tabScroller; + } + + void completeDeferredDestroyActionMode() { + if (mDeferredModeDestroyCallback != null) { + mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode); + mDeferredDestroyActionMode = null; + mDeferredModeDestroyCallback = null; + } + } + + /** + * Enables or disables animation between show/hide states. + * If animation is disabled using this method, animations in progress + * will be finished. + * + * @param enabled true to animate, false to not animate. + */ + public void setShowHideAnimationEnabled(boolean enabled) { + mShowHideAnimationEnabled = enabled; + if (!enabled && mCurrentShowAnim != null) { + mCurrentShowAnim.end(); + } + } + + public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + mMenuVisibilityListeners.add(listener); + } + + public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + mMenuVisibilityListeners.remove(listener); + } + + public void dispatchMenuVisibilityChanged(boolean isVisible) { + if (isVisible == mLastMenuVisibility) { + return; + } + mLastMenuVisibility = isVisible; + + final int count = mMenuVisibilityListeners.size(); + for (int i = 0; i < count; i++) { + mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible); + } + } + + @Override + public void setCustomView(int resId) { + setCustomView(LayoutInflater.from(getThemedContext()).inflate(resId, mActionView, false)); + } + + @Override + public void setDisplayUseLogoEnabled(boolean useLogo) { + setDisplayOptions(useLogo ? DISPLAY_USE_LOGO : 0, DISPLAY_USE_LOGO); + } + + @Override + public void setDisplayShowHomeEnabled(boolean showHome) { + setDisplayOptions(showHome ? DISPLAY_SHOW_HOME : 0, DISPLAY_SHOW_HOME); + } + + @Override + public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { + setDisplayOptions(showHomeAsUp ? DISPLAY_HOME_AS_UP : 0, DISPLAY_HOME_AS_UP); + } + + @Override + public void setDisplayShowTitleEnabled(boolean showTitle) { + setDisplayOptions(showTitle ? DISPLAY_SHOW_TITLE : 0, DISPLAY_SHOW_TITLE); + } + + @Override + public void setDisplayShowCustomEnabled(boolean showCustom) { + setDisplayOptions(showCustom ? DISPLAY_SHOW_CUSTOM : 0, DISPLAY_SHOW_CUSTOM); + } + + @Override + public void setHomeButtonEnabled(boolean enable) { + mActionView.setHomeButtonEnabled(enable); + } + + @Override + public void setTitle(int resId) { + setTitle(mContext.getString(resId)); + } + + @Override + public void setSubtitle(int resId) { + setSubtitle(mContext.getString(resId)); + } + + public void setSelectedNavigationItem(int position) { + switch (mActionView.getNavigationMode()) { + case NAVIGATION_MODE_TABS: + selectTab(mTabs.get(position)); + break; + case NAVIGATION_MODE_LIST: + mActionView.setDropdownSelectedPosition(position); + break; + default: + throw new IllegalStateException( + "setSelectedNavigationIndex not valid for current navigation mode"); + } + } + + public void removeAllTabs() { + cleanupTabs(); + } + + private void cleanupTabs() { + if (mSelectedTab != null) { + selectTab(null); + } + mTabs.clear(); + if (mTabScrollView != null) { + mTabScrollView.removeAllTabs(); + } + mSavedTabPosition = INVALID_POSITION; + } + + public void setTitle(CharSequence title) { + mActionView.setTitle(title); + } + + public void setSubtitle(CharSequence subtitle) { + mActionView.setSubtitle(subtitle); + } + + public void setDisplayOptions(int options) { + mActionView.setDisplayOptions(options); + } + + public void setDisplayOptions(int options, int mask) { + final int current = mActionView.getDisplayOptions(); + mActionView.setDisplayOptions((options & mask) | (current & ~mask)); + } + + public void setBackgroundDrawable(Drawable d) { + mContainerView.setPrimaryBackground(d); + } + + public void setStackedBackgroundDrawable(Drawable d) { + mContainerView.setStackedBackground(d); + } + + public void setSplitBackgroundDrawable(Drawable d) { + if (mSplitView != null) { + mSplitView.setSplitBackground(d); + } + } + + public View getCustomView() { + return mActionView.getCustomNavigationView(); + } + + public CharSequence getTitle() { + return mActionView.getTitle(); + } + + public CharSequence getSubtitle() { + return mActionView.getSubtitle(); + } + + public int getNavigationMode() { + return mActionView.getNavigationMode(); + } + + public int getDisplayOptions() { + return mActionView.getDisplayOptions(); + } + + public ActionMode startActionMode(ActionMode.Callback callback) { + boolean wasHidden = false; + if (mActionMode != null) { + wasHidden = mWasHiddenBeforeMode; + mActionMode.finish(); + } + + mContextView.killMode(); + ActionModeImpl mode = new ActionModeImpl(callback); + if (mode.dispatchOnCreate()) { + mWasHiddenBeforeMode = !isShowing() || wasHidden; + mode.invalidate(); + mContextView.initForMode(mode); + animateToMode(true); + if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { + // TODO animate this + mSplitView.setVisibility(View.VISIBLE); + } + mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + mActionMode = mode; + return mode; + } + return null; + } + + private void configureTab(Tab tab, int position) { + final TabImpl tabi = (TabImpl) tab; + final ActionBar.TabListener callback = tabi.getCallback(); + + if (callback == null) { + throw new IllegalStateException("Action Bar Tab must have a Callback"); + } + + tabi.setPosition(position); + mTabs.add(position, tabi); + + final int count = mTabs.size(); + for (int i = position + 1; i < count; i++) { + mTabs.get(i).setPosition(i); + } + } + + @Override + public void addTab(Tab tab) { + addTab(tab, mTabs.isEmpty()); + } + + @Override + public void addTab(Tab tab, int position) { + addTab(tab, position, mTabs.isEmpty()); + } + + @Override + public void addTab(Tab tab, boolean setSelected) { + ensureTabsExist(); + mTabScrollView.addTab(tab, setSelected); + configureTab(tab, mTabs.size()); + if (setSelected) { + selectTab(tab); + } + } + + @Override + public void addTab(Tab tab, int position, boolean setSelected) { + ensureTabsExist(); + mTabScrollView.addTab(tab, position, setSelected); + configureTab(tab, position); + if (setSelected) { + selectTab(tab); + } + } + + @Override + public Tab newTab() { + return new TabImpl(); + } + + @Override + public void removeTab(Tab tab) { + removeTabAt(tab.getPosition()); + } + + @Override + public void removeTabAt(int position) { + if (mTabScrollView == null) { + // No tabs around to remove + return; + } + + int selectedTabPosition = mSelectedTab != null + ? mSelectedTab.getPosition() : mSavedTabPosition; + mTabScrollView.removeTabAt(position); + TabImpl removedTab = mTabs.remove(position); + if (removedTab != null) { + removedTab.setPosition(-1); + } + + final int newTabCount = mTabs.size(); + for (int i = position; i < newTabCount; i++) { + mTabs.get(i).setPosition(i); + } + + if (selectedTabPosition == position) { + selectTab(mTabs.isEmpty() ? null : mTabs.get(Math.max(0, position - 1))); + } + } + + @Override + public void selectTab(Tab tab) { + if (getNavigationMode() != NAVIGATION_MODE_TABS) { + mSavedTabPosition = tab != null ? tab.getPosition() : INVALID_POSITION; + return; + } + + FragmentTransaction trans = null; + if (mActivity instanceof FragmentActivity) { + trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + .disallowAddToBackStack(); + } + + if (mSelectedTab == tab) { + if (mSelectedTab != null) { + mSelectedTab.getCallback().onTabReselected(mSelectedTab, trans); + mTabScrollView.animateToTab(tab.getPosition()); + } + } else { + mTabScrollView.setTabSelected(tab != null ? tab.getPosition() : Tab.INVALID_POSITION); + if (mSelectedTab != null) { + mSelectedTab.getCallback().onTabUnselected(mSelectedTab, trans); + } + mSelectedTab = (TabImpl) tab; + if (mSelectedTab != null) { + mSelectedTab.getCallback().onTabSelected(mSelectedTab, trans); + } + } + + if (trans != null && !trans.isEmpty()) { + trans.commit(); + } + } + + @Override + public Tab getSelectedTab() { + return mSelectedTab; + } + + @Override + public int getHeight() { + return mContainerView.getHeight(); + } + + @Override + public void show() { + show(true); + } + + void show(boolean markHiddenBeforeMode) { + if (mCurrentShowAnim != null) { + mCurrentShowAnim.end(); + } + if (mContainerView.getVisibility() == View.VISIBLE) { + if (markHiddenBeforeMode) mWasHiddenBeforeMode = false; + return; + } + mContainerView.setVisibility(View.VISIBLE); + + if (mShowHideAnimationEnabled) { + mContainerView.setAlpha(0); + AnimatorSet anim = new AnimatorSet(); + AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 1)); + if (mContentView != null) { + b.with(ObjectAnimator.ofFloat(mContentView, "translationY", + -mContainerView.getHeight(), 0)); + mContainerView.setTranslationY(-mContainerView.getHeight()); + b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", 0)); + } + if (mSplitView != null && mContextDisplayMode == CONTEXT_DISPLAY_SPLIT) { + mSplitView.setAlpha(0); + mSplitView.setVisibility(View.VISIBLE); + b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 1)); + } + anim.addListener(mShowListener); + mCurrentShowAnim = anim; + anim.start(); + } else { + mContainerView.setAlpha(1); + mContainerView.setTranslationY(0); + mShowListener.onAnimationEnd(null); + } + } + + @Override + public void hide() { + if (mCurrentShowAnim != null) { + mCurrentShowAnim.end(); + } + if (mContainerView.getVisibility() == View.GONE) { + return; + } + + if (mShowHideAnimationEnabled) { + mContainerView.setAlpha(1); + mContainerView.setTransitioning(true); + AnimatorSet anim = new AnimatorSet(); + AnimatorSet.Builder b = anim.play(ObjectAnimator.ofFloat(mContainerView, "alpha", 0)); + if (mContentView != null) { + b.with(ObjectAnimator.ofFloat(mContentView, "translationY", + 0, -mContainerView.getHeight())); + b.with(ObjectAnimator.ofFloat(mContainerView, "translationY", + -mContainerView.getHeight())); + } + if (mSplitView != null && mSplitView.getVisibility() == View.VISIBLE) { + mSplitView.setAlpha(1); + b.with(ObjectAnimator.ofFloat(mSplitView, "alpha", 0)); + } + anim.addListener(mHideListener); + mCurrentShowAnim = anim; + anim.start(); + } else { + mHideListener.onAnimationEnd(null); + } + } + + public boolean isShowing() { + return mContainerView.getVisibility() == View.VISIBLE; + } + + void animateToMode(boolean toActionMode) { + if (toActionMode) { + show(false); + } + if (mCurrentModeAnim != null) { + mCurrentModeAnim.end(); + } + + mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); + mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE); + if (mTabScrollView != null && !mActionView.hasEmbeddedTabs() && mActionView.isCollapsed()) { + mTabScrollView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE); + } + } + + public Context getThemedContext() { + if (mThemedContext == null) { + TypedValue outValue = new TypedValue(); + Resources.Theme currentTheme = mContext.getTheme(); + currentTheme.resolveAttribute(R.attr.actionBarWidgetTheme, + outValue, true); + final int targetThemeRes = outValue.resourceId; + + if (targetThemeRes != 0) { //XXX && mContext.getThemeResId() != targetThemeRes) { + mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes); + } else { + mThemedContext = mContext; + } + } + return mThemedContext; + } + + /** + * @hide + */ + public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback { + private ActionMode.Callback mCallback; + private MenuBuilder mMenu; + private WeakReference mCustomView; + + public ActionModeImpl(ActionMode.Callback callback) { + mCallback = callback; + mMenu = new MenuBuilder(getThemedContext()) + .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + mMenu.setCallback(this); + } + + @Override + public MenuInflater getMenuInflater() { + return new MenuInflater(getThemedContext()); + } + + @Override + public Menu getMenu() { + return mMenu; + } + + @Override + public void finish() { + if (mActionMode != this) { + // Not the active action mode - no-op + return; + } + + // If we were hidden before the mode was shown, defer the onDestroy + // callback until the animation is finished and associated relayout + // is about to happen. This lets apps better anticipate visibility + // and layout behavior. + if (mWasHiddenBeforeMode) { + mDeferredDestroyActionMode = this; + mDeferredModeDestroyCallback = mCallback; + } else { + mCallback.onDestroyActionMode(this); + } + mCallback = null; + animateToMode(false); + + // Clear out the context mode views after the animation finishes + mContextView.closeMode(); + mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + + mActionMode = null; + + if (mWasHiddenBeforeMode) { + hide(); + } + } + + @Override + public void invalidate() { + mMenu.stopDispatchingItemsChanged(); + try { + mCallback.onPrepareActionMode(this, mMenu); + } finally { + mMenu.startDispatchingItemsChanged(); + } + } + + public boolean dispatchOnCreate() { + mMenu.stopDispatchingItemsChanged(); + try { + return mCallback.onCreateActionMode(this, mMenu); + } finally { + mMenu.startDispatchingItemsChanged(); + } + } + + @Override + public void setCustomView(View view) { + mContextView.setCustomView(view); + mCustomView = new WeakReference(view); + } + + @Override + public void setSubtitle(CharSequence subtitle) { + mContextView.setSubtitle(subtitle); + } + + @Override + public void setTitle(CharSequence title) { + mContextView.setTitle(title); + } + + @Override + public void setTitle(int resId) { + setTitle(mContext.getResources().getString(resId)); + } + + @Override + public void setSubtitle(int resId) { + setSubtitle(mContext.getResources().getString(resId)); + } + + @Override + public CharSequence getTitle() { + return mContextView.getTitle(); + } + + @Override + public CharSequence getSubtitle() { + return mContextView.getSubtitle(); + } + + @Override + public View getCustomView() { + return mCustomView != null ? mCustomView.get() : null; + } + + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { + if (mCallback != null) { + return mCallback.onActionItemClicked(this, item); + } else { + return false; + } + } + + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + } + + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + if (mCallback == null) { + return false; + } + + if (!subMenu.hasVisibleItems()) { + return true; + } + + new MenuPopupHelper(getThemedContext(), subMenu).show(); + return true; + } + + public void onCloseSubMenu(SubMenuBuilder menu) { + } + + public void onMenuModeChange(MenuBuilder menu) { + if (mCallback == null) { + return; + } + invalidate(); + mContextView.showOverflowMenu(); + } + } + + /** + * @hide + */ + public class TabImpl extends ActionBar.Tab { + private ActionBar.TabListener mCallback; + private Object mTag; + private Drawable mIcon; + private CharSequence mText; + private CharSequence mContentDesc; + private int mPosition = -1; + private View mCustomView; + + @Override + public Object getTag() { + return mTag; + } + + @Override + public Tab setTag(Object tag) { + mTag = tag; + return this; + } + + public ActionBar.TabListener getCallback() { + return mCallback; + } + + @Override + public Tab setTabListener(ActionBar.TabListener callback) { + mCallback = callback; + return this; + } + + @Override + public View getCustomView() { + return mCustomView; + } + + @Override + public Tab setCustomView(View view) { + mCustomView = view; + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } + return this; + } + + @Override + public Tab setCustomView(int layoutResId) { + return setCustomView(LayoutInflater.from(getThemedContext()) + .inflate(layoutResId, null)); + } + + @Override + public Drawable getIcon() { + return mIcon; + } + + @Override + public int getPosition() { + return mPosition; + } + + public void setPosition(int position) { + mPosition = position; + } + + @Override + public CharSequence getText() { + return mText; + } + + @Override + public Tab setIcon(Drawable icon) { + mIcon = icon; + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } + return this; + } + + @Override + public Tab setIcon(int resId) { + return setIcon(mContext.getResources().getDrawable(resId)); + } + + @Override + public Tab setText(CharSequence text) { + mText = text; + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } + return this; + } + + @Override + public Tab setText(int resId) { + return setText(mContext.getResources().getText(resId)); + } + + @Override + public void select() { + selectTab(this); + } + + @Override + public Tab setContentDescription(int resId) { + return setContentDescription(mContext.getResources().getText(resId)); + } + + @Override + public Tab setContentDescription(CharSequence contentDesc) { + mContentDesc = contentDesc; + if (mPosition >= 0) { + mTabScrollView.updateTab(mPosition); + } + return this; + } + + @Override + public CharSequence getContentDescription() { + return mContentDesc; + } + } + + @Override + public void setCustomView(View view) { + mActionView.setCustomNavigationView(view); + } + + @Override + public void setCustomView(View view, LayoutParams layoutParams) { + view.setLayoutParams(layoutParams); + mActionView.setCustomNavigationView(view); + } + + @Override + public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { + mActionView.setDropdownAdapter(adapter); + mActionView.setCallback(callback); + } + + @Override + public int getSelectedNavigationIndex() { + switch (mActionView.getNavigationMode()) { + case NAVIGATION_MODE_TABS: + return mSelectedTab != null ? mSelectedTab.getPosition() : -1; + case NAVIGATION_MODE_LIST: + return mActionView.getDropdownSelectedPosition(); + default: + return -1; + } + } + + @Override + public int getNavigationItemCount() { + switch (mActionView.getNavigationMode()) { + case NAVIGATION_MODE_TABS: + return mTabs.size(); + case NAVIGATION_MODE_LIST: + SpinnerAdapter adapter = mActionView.getDropdownAdapter(); + return adapter != null ? adapter.getCount() : 0; + default: + return 0; + } + } + + @Override + public int getTabCount() { + return mTabs.size(); + } + + @Override + public void setNavigationMode(int mode) { + final int oldMode = mActionView.getNavigationMode(); + switch (oldMode) { + case NAVIGATION_MODE_TABS: + mSavedTabPosition = getSelectedNavigationIndex(); + selectTab(null); + mTabScrollView.setVisibility(View.GONE); + break; + } + mActionView.setNavigationMode(mode); + switch (mode) { + case NAVIGATION_MODE_TABS: + ensureTabsExist(); + mTabScrollView.setVisibility(View.VISIBLE); + if (mSavedTabPosition != INVALID_POSITION) { + setSelectedNavigationItem(mSavedTabPosition); + mSavedTabPosition = INVALID_POSITION; + } + break; + } + mActionView.setCollapsable(mode == NAVIGATION_MODE_TABS && !mHasEmbeddedTabs); + } + + @Override + public Tab getTabAt(int index) { + return mTabs.get(index); + } + + + @Override + public void setIcon(int resId) { + mActionView.setIcon(resId); + } + + @Override + public void setIcon(Drawable icon) { + mActionView.setIcon(icon); + } + + @Override + public void setLogo(int resId) { + mActionView.setLogo(resId); + } + + @Override + public void setLogo(Drawable logo) { + mActionView.setLogo(logo); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java new file mode 100644 index 000000000..840cb3d27 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/app/ActionBarWrapper.java @@ -0,0 +1,468 @@ +package com.actionbarsherlock.internal.app; + +import java.util.HashSet; +import java.util.Set; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentTransaction; +import android.view.View; +import android.widget.SpinnerAdapter; + +import com.actionbarsherlock.app.ActionBar; + +public class ActionBarWrapper extends ActionBar implements android.app.ActionBar.OnNavigationListener, android.app.ActionBar.OnMenuVisibilityListener { + private final Activity mActivity; + private final android.app.ActionBar mActionBar; + private ActionBar.OnNavigationListener mNavigationListener; + private Set mMenuVisibilityListeners = new HashSet(1); + private FragmentTransaction mFragmentTransaction; + + + public ActionBarWrapper(Activity activity) { + mActivity = activity; + mActionBar = activity.getActionBar(); + if (mActionBar != null) { + mActionBar.addOnMenuVisibilityListener(this); + } + } + + + @Override + public void setHomeButtonEnabled(boolean enabled) { + mActionBar.setHomeButtonEnabled(enabled); + } + + @Override + public Context getThemedContext() { + return mActionBar.getThemedContext(); + } + + @Override + public void setCustomView(View view) { + mActionBar.setCustomView(view); + } + + @Override + public void setCustomView(View view, LayoutParams layoutParams) { + android.app.ActionBar.LayoutParams lp = new android.app.ActionBar.LayoutParams(layoutParams); + lp.gravity = layoutParams.gravity; + lp.bottomMargin = layoutParams.bottomMargin; + lp.topMargin = layoutParams.topMargin; + lp.leftMargin = layoutParams.leftMargin; + lp.rightMargin = layoutParams.rightMargin; + mActionBar.setCustomView(view, lp); + } + + @Override + public void setCustomView(int resId) { + mActionBar.setCustomView(resId); + } + + @Override + public void setIcon(int resId) { + mActionBar.setIcon(resId); + } + + @Override + public void setIcon(Drawable icon) { + mActionBar.setIcon(icon); + } + + @Override + public void setLogo(int resId) { + mActionBar.setLogo(resId); + } + + @Override + public void setLogo(Drawable logo) { + mActionBar.setLogo(logo); + } + + @Override + public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { + mNavigationListener = callback; + mActionBar.setListNavigationCallbacks(adapter, (callback != null) ? this : null); + } + + @Override + public boolean onNavigationItemSelected(int itemPosition, long itemId) { + //This should never be a NullPointerException since we only set + //ourselves as the listener when the callback is not null. + return mNavigationListener.onNavigationItemSelected(itemPosition, itemId); + } + + @Override + public void setSelectedNavigationItem(int position) { + mActionBar.setSelectedNavigationItem(position); + } + + @Override + public int getSelectedNavigationIndex() { + return mActionBar.getSelectedNavigationIndex(); + } + + @Override + public int getNavigationItemCount() { + return mActionBar.getNavigationItemCount(); + } + + @Override + public void setTitle(CharSequence title) { + mActionBar.setTitle(title); + } + + @Override + public void setTitle(int resId) { + mActionBar.setTitle(resId); + } + + @Override + public void setSubtitle(CharSequence subtitle) { + mActionBar.setSubtitle(subtitle); + } + + @Override + public void setSubtitle(int resId) { + mActionBar.setSubtitle(resId); + } + + @Override + public void setDisplayOptions(int options) { + mActionBar.setDisplayOptions(options); + } + + @Override + public void setDisplayOptions(int options, int mask) { + mActionBar.setDisplayOptions(options, mask); + } + + @Override + public void setDisplayUseLogoEnabled(boolean useLogo) { + mActionBar.setDisplayUseLogoEnabled(useLogo); + } + + @Override + public void setDisplayShowHomeEnabled(boolean showHome) { + mActionBar.setDisplayShowHomeEnabled(showHome); + } + + @Override + public void setDisplayHomeAsUpEnabled(boolean showHomeAsUp) { + mActionBar.setDisplayHomeAsUpEnabled(showHomeAsUp); + } + + @Override + public void setDisplayShowTitleEnabled(boolean showTitle) { + mActionBar.setDisplayShowTitleEnabled(showTitle); + } + + @Override + public void setDisplayShowCustomEnabled(boolean showCustom) { + mActionBar.setDisplayShowCustomEnabled(showCustom); + } + + @Override + public void setBackgroundDrawable(Drawable d) { + mActionBar.setBackgroundDrawable(d); + } + + @Override + public void setStackedBackgroundDrawable(Drawable d) { + mActionBar.setStackedBackgroundDrawable(d); + } + + @Override + public void setSplitBackgroundDrawable(Drawable d) { + mActionBar.setSplitBackgroundDrawable(d); + } + + @Override + public View getCustomView() { + return mActionBar.getCustomView(); + } + + @Override + public CharSequence getTitle() { + return mActionBar.getTitle(); + } + + @Override + public CharSequence getSubtitle() { + return mActionBar.getSubtitle(); + } + + @Override + public int getNavigationMode() { + return mActionBar.getNavigationMode(); + } + + @Override + public void setNavigationMode(int mode) { + mActionBar.setNavigationMode(mode); + } + + @Override + public int getDisplayOptions() { + return mActionBar.getDisplayOptions(); + } + + public class TabWrapper extends ActionBar.Tab implements android.app.ActionBar.TabListener { + final android.app.ActionBar.Tab mNativeTab; + private Object mTag; + private TabListener mListener; + + public TabWrapper(android.app.ActionBar.Tab nativeTab) { + mNativeTab = nativeTab; + mNativeTab.setTag(this); + } + + @Override + public int getPosition() { + return mNativeTab.getPosition(); + } + + @Override + public Drawable getIcon() { + return mNativeTab.getIcon(); + } + + @Override + public CharSequence getText() { + return mNativeTab.getText(); + } + + @Override + public Tab setIcon(Drawable icon) { + mNativeTab.setIcon(icon); + return this; + } + + @Override + public Tab setIcon(int resId) { + mNativeTab.setIcon(resId); + return this; + } + + @Override + public Tab setText(CharSequence text) { + mNativeTab.setText(text); + return this; + } + + @Override + public Tab setText(int resId) { + mNativeTab.setText(resId); + return this; + } + + @Override + public Tab setCustomView(View view) { + mNativeTab.setCustomView(view); + return this; + } + + @Override + public Tab setCustomView(int layoutResId) { + mNativeTab.setCustomView(layoutResId); + return this; + } + + @Override + public View getCustomView() { + return mNativeTab.getCustomView(); + } + + @Override + public Tab setTag(Object obj) { + mTag = obj; + return this; + } + + @Override + public Object getTag() { + return mTag; + } + + @Override + public Tab setTabListener(TabListener listener) { + mNativeTab.setTabListener(listener != null ? this : null); + mListener = listener; + return this; + } + + @Override + public void select() { + mNativeTab.select(); + } + + @Override + public Tab setContentDescription(int resId) { + mNativeTab.setContentDescription(resId); + return this; + } + + @Override + public Tab setContentDescription(CharSequence contentDesc) { + mNativeTab.setContentDescription(contentDesc); + return this; + } + + @Override + public CharSequence getContentDescription() { + return mNativeTab.getContentDescription(); + } + + @Override + public void onTabReselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { + if (mListener != null) { + FragmentTransaction trans = null; + if (mActivity instanceof FragmentActivity) { + trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + .disallowAddToBackStack(); + } + + mListener.onTabReselected(this, trans); + + if (trans != null && !trans.isEmpty()) { + trans.commit(); + } + } + } + + @Override + public void onTabSelected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { + if (mListener != null) { + + if (mFragmentTransaction == null && mActivity instanceof FragmentActivity) { + mFragmentTransaction = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + .disallowAddToBackStack(); + } + + mListener.onTabSelected(this, mFragmentTransaction); + + if (mFragmentTransaction != null) { + if (!mFragmentTransaction.isEmpty()) { + mFragmentTransaction.commit(); + } + mFragmentTransaction = null; + } + } + } + + @Override + public void onTabUnselected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) { + if (mListener != null) { + FragmentTransaction trans = null; + if (mActivity instanceof FragmentActivity) { + trans = ((FragmentActivity)mActivity).getSupportFragmentManager().beginTransaction() + .disallowAddToBackStack(); + mFragmentTransaction = trans; + } + + mListener.onTabUnselected(this, trans); + } + } + } + + @Override + public Tab newTab() { + return new TabWrapper(mActionBar.newTab()); + } + + @Override + public void addTab(Tab tab) { + mActionBar.addTab(((TabWrapper)tab).mNativeTab); + } + + @Override + public void addTab(Tab tab, boolean setSelected) { + mActionBar.addTab(((TabWrapper)tab).mNativeTab, setSelected); + } + + @Override + public void addTab(Tab tab, int position) { + mActionBar.addTab(((TabWrapper)tab).mNativeTab, position); + } + + @Override + public void addTab(Tab tab, int position, boolean setSelected) { + mActionBar.addTab(((TabWrapper)tab).mNativeTab, position, setSelected); + } + + @Override + public void removeTab(Tab tab) { + mActionBar.removeTab(((TabWrapper)tab).mNativeTab); + } + + @Override + public void removeTabAt(int position) { + mActionBar.removeTabAt(position); + } + + @Override + public void removeAllTabs() { + mActionBar.removeAllTabs(); + } + + @Override + public void selectTab(Tab tab) { + mActionBar.selectTab(((TabWrapper)tab).mNativeTab); + } + + @Override + public Tab getSelectedTab() { + android.app.ActionBar.Tab selected = mActionBar.getSelectedTab(); + return (selected != null) ? (Tab)selected.getTag() : null; + } + + @Override + public Tab getTabAt(int index) { + android.app.ActionBar.Tab selected = mActionBar.getTabAt(index); + return (selected != null) ? (Tab)selected.getTag() : null; + } + + @Override + public int getTabCount() { + return mActionBar.getTabCount(); + } + + @Override + public int getHeight() { + return mActionBar.getHeight(); + } + + @Override + public void show() { + mActionBar.show(); + } + + @Override + public void hide() { + mActionBar.hide(); + } + + @Override + public boolean isShowing() { + return mActionBar.isShowing(); + } + + @Override + public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + mMenuVisibilityListeners.add(listener); + } + + @Override + public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + mMenuVisibilityListeners.remove(listener); + } + + @Override + public void onMenuVisibilityChanged(boolean isVisible) { + for (OnMenuVisibilityListener listener : mMenuVisibilityListeners) { + listener.onMenuVisibilityChanged(isVisible); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java new file mode 100644 index 000000000..2caf5b4a9 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import java.util.ArrayList; + +import android.view.animation.Interpolator; + +/** + * This is the superclass for classes which provide basic support for animations which can be + * started, ended, and have AnimatorListeners added to them. + */ +public abstract class Animator implements Cloneable { + + + /** + * The set of listeners to be sent events through the life of an animation. + */ + ArrayList mListeners = null; + + /** + * Starts this animation. If the animation has a nonzero startDelay, the animation will start + * running after that delay elapses. A non-delayed animation will have its initial + * value(s) set immediately, followed by calls to + * {@link AnimatorListener#onAnimationStart(Animator)} for any listeners of this animator. + * + *

The animation started by calling this method will be run on the thread that called + * this method. This thread should have a Looper on it (a runtime exception will be thrown if + * this is not the case). Also, if the animation will animate + * properties of objects in the view hierarchy, then the calling thread should be the UI + * thread for that view hierarchy.

+ * + */ + public void start() { + } + + /** + * Cancels the animation. Unlike {@link #end()}, cancel() causes the animation to + * stop in its tracks, sending an + * {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to + * its listeners, followed by an + * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message. + * + *

This method must be called on the thread that is running the animation.

+ */ + public void cancel() { + } + + /** + * Ends the animation. This causes the animation to assign the end value of the property being + * animated, then calling the + * {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on + * its listeners. + * + *

This method must be called on the thread that is running the animation.

+ */ + public void end() { + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + * + * @return the number of milliseconds to delay running the animation + */ + public abstract long getStartDelay(); + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + + * @param startDelay The amount of the delay, in milliseconds + */ + public abstract void setStartDelay(long startDelay); + + + /** + * Sets the length of the animation. + * + * @param duration The length of the animation, in milliseconds. + */ + public abstract Animator setDuration(long duration); + + /** + * Gets the length of the animation. + * + * @return The length of the animation, in milliseconds. + */ + public abstract long getDuration(); + + /** + * The time interpolator used in calculating the elapsed fraction of this animation. The + * interpolator determines whether the animation runs with linear or non-linear motion, + * such as acceleration and deceleration. The default value is + * {@link android.view.animation.AccelerateDecelerateInterpolator} + * + * @param value the interpolator to be used by this animation + */ + public abstract void setInterpolator(/*Time*/Interpolator value); + + /** + * Returns whether this Animator is currently running (having been started and gone past any + * initial startDelay period and not yet ended). + * + * @return Whether the Animator is running. + */ + public abstract boolean isRunning(); + + /** + * Returns whether this Animator has been started and not yet ended. This state is a superset + * of the state of {@link #isRunning()}, because an Animator with a nonzero + * {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during the + * delay phase, whereas {@link #isRunning()} will return true only after the delay phase + * is complete. + * + * @return Whether the Animator has been started and not yet ended. + */ + public boolean isStarted() { + // Default method returns value for isRunning(). Subclasses should override to return a + // real value. + return isRunning(); + } + + /** + * Adds a listener to the set of listeners that are sent events through the life of an + * animation, such as start, repeat, and end. + * + * @param listener the listener to be added to the current set of listeners for this animation. + */ + public void addListener(AnimatorListener listener) { + if (mListeners == null) { + mListeners = new ArrayList(); + } + mListeners.add(listener); + } + + /** + * Removes a listener from the set listening to this animation. + * + * @param listener the listener to be removed from the current set of listeners for this + * animation. + */ + public void removeListener(AnimatorListener listener) { + if (mListeners == null) { + return; + } + mListeners.remove(listener); + if (mListeners.size() == 0) { + mListeners = null; + } + } + + /** + * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently + * listening for events on this Animator object. + * + * @return ArrayList The set of listeners. + */ + public ArrayList getListeners() { + return mListeners; + } + + /** + * Removes all listeners from this object. This is equivalent to calling + * getListeners() followed by calling clear() on the + * returned list of listeners. + */ + public void removeAllListeners() { + if (mListeners != null) { + mListeners.clear(); + mListeners = null; + } + } + + @Override + public Animator clone() { + try { + final Animator anim = (Animator) super.clone(); + if (mListeners != null) { + ArrayList oldListeners = mListeners; + anim.mListeners = new ArrayList(); + int numListeners = oldListeners.size(); + for (int i = 0; i < numListeners; ++i) { + anim.mListeners.add(oldListeners.get(i)); + } + } + return anim; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + + /** + * This method tells the object to use appropriate information to extract + * starting values for the animation. For example, a AnimatorSet object will pass + * this call to its child objects to tell them to set up the values. A + * ObjectAnimator object will use the information it has about its target object + * and PropertyValuesHolder objects to get the start values for its properties. + * An ValueAnimator object will ignore the request since it does not have enough + * information (such as a target object) to gather these values. + */ + public void setupStartValues() { + } + + /** + * This method tells the object to use appropriate information to extract + * ending values for the animation. For example, a AnimatorSet object will pass + * this call to its child objects to tell them to set up the values. A + * ObjectAnimator object will use the information it has about its target object + * and PropertyValuesHolder objects to get the start values for its properties. + * An ValueAnimator object will ignore the request since it does not have enough + * information (such as a target object) to gather these values. + */ + public void setupEndValues() { + } + + /** + * Sets the target object whose property will be animated by this animation. Not all subclasses + * operate on target objects (for example, {@link ValueAnimator}, but this method + * is on the superclass for the convenience of dealing generically with those subclasses + * that do handle targets. + * + * @param target The object being animated + */ + public void setTarget(Object target) { + } + + /** + *

An animation listener receives notifications from an animation. + * Notifications indicate animation related events, such as the end or the + * repetition of the animation.

+ */ + public static interface AnimatorListener { + /** + *

Notifies the start of the animation.

+ * + * @param animation The started animation. + */ + void onAnimationStart(Animator animation); + + /** + *

Notifies the end of the animation. This callback is not invoked + * for animations with repeat count set to INFINITE.

+ * + * @param animation The animation which reached its end. + */ + void onAnimationEnd(Animator animation); + + /** + *

Notifies the cancellation of the animation. This callback is not invoked + * for animations with repeat count set to INFINITE.

+ * + * @param animation The animation which was canceled. + */ + void onAnimationCancel(Animator animation); + + /** + *

Notifies the repetition of the animation.

+ * + * @param animation The animation which was repeated. + */ + void onAnimationRepeat(Animator animation); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java new file mode 100644 index 000000000..02ddff48d --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +/** + * This adapter class provides empty implementations of the methods from {@link android.animation.Animator.AnimatorListener}. + * Any custom listener that cares only about a subset of the methods of this listener can + * simply subclass this adapter class instead of implementing the interface directly. + */ +public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener { + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationCancel(Animator animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationEnd(Animator animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationRepeat(Animator animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationStart(Animator animation) { + } + +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java new file mode 100644 index 000000000..3231080c4 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java @@ -0,0 +1,1111 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import android.view.animation.Interpolator; + +/** + * This class plays a set of {@link Animator} objects in the specified order. Animations + * can be set up to play together, in sequence, or after a specified delay. + * + *

There are two different approaches to adding animations to a AnimatorSet: + * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or + * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add + * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be + * used in conjunction with methods in the {@link AnimatorSet.Builder Builder} + * class to add animations + * one by one.

+ * + *

It is possible to set up a AnimatorSet with circular dependencies between + * its animations. For example, an animation a1 could be set up to start before animation a2, a2 + * before a3, and a3 before a1. The results of this configuration are undefined, but will typically + * result in none of the affected animations being played. Because of this (and because + * circular dependencies do not make logical sense anyway), circular dependencies + * should be avoided, and the dependency flow of animations should only be in one direction. + */ +@SuppressWarnings("unchecked") +public final class AnimatorSet extends Animator { + + /** + * Internal variables + * NOTE: This object implements the clone() method, making a deep copy of any referenced + * objects. As other non-trivial fields are added to this class, make sure to add logic + * to clone() to make deep copies of them. + */ + + /** + * Tracks animations currently being played, so that we know what to + * cancel or end when cancel() or end() is called on this AnimatorSet + */ + private ArrayList mPlayingSet = new ArrayList(); + + /** + * Contains all nodes, mapped to their respective Animators. When new + * dependency information is added for an Animator, we want to add it + * to a single node representing that Animator, not create a new Node + * if one already exists. + */ + private HashMap mNodeMap = new HashMap(); + + /** + * Set of all nodes created for this AnimatorSet. This list is used upon + * starting the set, and the nodes are placed in sorted order into the + * sortedNodes collection. + */ + private ArrayList mNodes = new ArrayList(); + + /** + * The sorted list of nodes. This is the order in which the animations will + * be played. The details about when exactly they will be played depend + * on the dependency relationships of the nodes. + */ + private ArrayList mSortedNodes = new ArrayList(); + + /** + * Flag indicating whether the nodes should be sorted prior to playing. This + * flag allows us to cache the previous sorted nodes so that if the sequence + * is replayed with no changes, it does not have to re-sort the nodes again. + */ + private boolean mNeedsSort = true; + + private AnimatorSetListener mSetListener = null; + + /** + * Flag indicating that the AnimatorSet has been manually + * terminated (by calling cancel() or end()). + * This flag is used to avoid starting other animations when currently-playing + * child animations of this AnimatorSet end. It also determines whether cancel/end + * notifications are sent out via the normal AnimatorSetListener mechanism. + */ + boolean mTerminated = false; + + /** + * Indicates whether an AnimatorSet has been start()'d, whether or + * not there is a nonzero startDelay. + */ + private boolean mStarted = false; + + // The amount of time in ms to delay starting the animation after start() is called + private long mStartDelay = 0; + + // Animator used for a nonzero startDelay + private ValueAnimator mDelayAnim = null; + + + // How long the child animations should last in ms. The default value is negative, which + // simply means that there is no duration set on the AnimatorSet. When a real duration is + // set, it is passed along to the child animations. + private long mDuration = -1; + + + /** + * Sets up this AnimatorSet to play all of the supplied animations at the same time. + * + * @param items The animations that will be started simultaneously. + */ + public void playTogether(Animator... items) { + if (items != null) { + mNeedsSort = true; + Builder builder = play(items[0]); + for (int i = 1; i < items.length; ++i) { + builder.with(items[i]); + } + } + } + + /** + * Sets up this AnimatorSet to play all of the supplied animations at the same time. + * + * @param items The animations that will be started simultaneously. + */ + public void playTogether(Collection items) { + if (items != null && items.size() > 0) { + mNeedsSort = true; + Builder builder = null; + for (Animator anim : items) { + if (builder == null) { + builder = play(anim); + } else { + builder.with(anim); + } + } + } + } + + /** + * Sets up this AnimatorSet to play each of the supplied animations when the + * previous animation ends. + * + * @param items The animations that will be started one after another. + */ + public void playSequentially(Animator... items) { + if (items != null) { + mNeedsSort = true; + if (items.length == 1) { + play(items[0]); + } else { + for (int i = 0; i < items.length - 1; ++i) { + play(items[i]).before(items[i+1]); + } + } + } + } + + /** + * Sets up this AnimatorSet to play each of the supplied animations when the + * previous animation ends. + * + * @param items The animations that will be started one after another. + */ + public void playSequentially(List items) { + if (items != null && items.size() > 0) { + mNeedsSort = true; + if (items.size() == 1) { + play(items.get(0)); + } else { + for (int i = 0; i < items.size() - 1; ++i) { + play(items.get(i)).before(items.get(i+1)); + } + } + } + } + + /** + * Returns the current list of child Animator objects controlled by this + * AnimatorSet. This is a copy of the internal list; modifications to the returned list + * will not affect the AnimatorSet, although changes to the underlying Animator objects + * will affect those objects being managed by the AnimatorSet. + * + * @return ArrayList The list of child animations of this AnimatorSet. + */ + public ArrayList getChildAnimations() { + ArrayList childList = new ArrayList(); + for (Node node : mNodes) { + childList.add(node.animation); + } + return childList; + } + + /** + * Sets the target object for all current {@link #getChildAnimations() child animations} + * of this AnimatorSet that take targets ({@link ObjectAnimator} and + * AnimatorSet). + * + * @param target The object being animated + */ + @Override + public void setTarget(Object target) { + for (Node node : mNodes) { + Animator animation = node.animation; + if (animation instanceof AnimatorSet) { + ((AnimatorSet)animation).setTarget(target); + } else if (animation instanceof ObjectAnimator) { + ((ObjectAnimator)animation).setTarget(target); + } + } + } + + /** + * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations} + * of this AnimatorSet. + * + * @param interpolator the interpolator to be used by each child animation of this AnimatorSet + */ + @Override + public void setInterpolator(/*Time*/Interpolator interpolator) { + for (Node node : mNodes) { + node.animation.setInterpolator(interpolator); + } + } + + /** + * This method creates a Builder object, which is used to + * set up playing constraints. This initial play() method + * tells the Builder the animation that is the dependency for + * the succeeding commands to the Builder. For example, + * calling play(a1).with(a2) sets up the AnimatorSet to play + * a1 and a2 at the same time, + * play(a1).before(a2) sets up the AnimatorSet to play + * a1 first, followed by a2, and + * play(a1).after(a2) sets up the AnimatorSet to play + * a2 first, followed by a1. + * + *

Note that play() is the only way to tell the + * Builder the animation upon which the dependency is created, + * so successive calls to the various functions in Builder + * will all refer to the initial parameter supplied in play() + * as the dependency of the other animations. For example, calling + * play(a1).before(a2).before(a3) will play both a2 + * and a3 when a1 ends; it does not set up a dependency between + * a2 and a3.

+ * + * @param anim The animation that is the dependency used in later calls to the + * methods in the returned Builder object. A null parameter will result + * in a null Builder return value. + * @return Builder The object that constructs the AnimatorSet based on the dependencies + * outlined in the calls to play and the other methods in the + * BuilderNote that canceling a AnimatorSet also cancels all of the animations that it + * is responsible for.

+ */ + @Override + public void cancel() { + mTerminated = true; + if (isStarted()) { + ArrayList tmpListeners = null; + if (mListeners != null) { + tmpListeners = (ArrayList) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationCancel(this); + } + } + if (mDelayAnim != null && mDelayAnim.isRunning()) { + // If we're currently in the startDelay period, just cancel that animator and + // send out the end event to all listeners + mDelayAnim.cancel(); + } else if (mSortedNodes.size() > 0) { + for (Node node : mSortedNodes) { + node.animation.cancel(); + } + } + if (tmpListeners != null) { + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationEnd(this); + } + } + mStarted = false; + } + } + + /** + * {@inheritDoc} + * + *

Note that ending a AnimatorSet also ends all of the animations that it is + * responsible for.

+ */ + @Override + public void end() { + mTerminated = true; + if (isStarted()) { + if (mSortedNodes.size() != mNodes.size()) { + // hasn't been started yet - sort the nodes now, then end them + sortNodes(); + for (Node node : mSortedNodes) { + if (mSetListener == null) { + mSetListener = new AnimatorSetListener(this); + } + node.animation.addListener(mSetListener); + } + } + if (mDelayAnim != null) { + mDelayAnim.cancel(); + } + if (mSortedNodes.size() > 0) { + for (Node node : mSortedNodes) { + node.animation.end(); + } + } + if (mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationEnd(this); + } + } + mStarted = false; + } + } + + /** + * Returns true if any of the child animations of this AnimatorSet have been started and have + * not yet ended. + * @return Whether this AnimatorSet has been started and has not yet ended. + */ + @Override + public boolean isRunning() { + for (Node node : mNodes) { + if (node.animation.isRunning()) { + return true; + } + } + return false; + } + + @Override + public boolean isStarted() { + return mStarted; + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + * + * @return the number of milliseconds to delay running the animation + */ + @Override + public long getStartDelay() { + return mStartDelay; + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + + * @param startDelay The amount of the delay, in milliseconds + */ + @Override + public void setStartDelay(long startDelay) { + mStartDelay = startDelay; + } + + /** + * Gets the length of each of the child animations of this AnimatorSet. This value may + * be less than 0, which indicates that no duration has been set on this AnimatorSet + * and each of the child animations will use their own duration. + * + * @return The length of the animation, in milliseconds, of each of the child + * animations of this AnimatorSet. + */ + @Override + public long getDuration() { + return mDuration; + } + + /** + * Sets the length of each of the current child animations of this AnimatorSet. By default, + * each child animation will use its own duration. If the duration is set on the AnimatorSet, + * then each child animation inherits this duration. + * + * @param duration The length of the animation, in milliseconds, of each of the child + * animations of this AnimatorSet. + */ + @Override + public AnimatorSet setDuration(long duration) { + if (duration < 0) { + throw new IllegalArgumentException("duration must be a value of zero or greater"); + } + for (Node node : mNodes) { + // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to + // insert "play-after" delays + node.animation.setDuration(duration); + } + mDuration = duration; + return this; + } + + @Override + public void setupStartValues() { + for (Node node : mNodes) { + node.animation.setupStartValues(); + } + } + + @Override + public void setupEndValues() { + for (Node node : mNodes) { + node.animation.setupEndValues(); + } + } + + /** + * {@inheritDoc} + * + *

Starting this AnimatorSet will, in turn, start the animations for which + * it is responsible. The details of when exactly those animations are started depends on + * the dependency relationships that have been set up between the animations. + */ + @Override + public void start() { + mTerminated = false; + mStarted = true; + + // First, sort the nodes (if necessary). This will ensure that sortedNodes + // contains the animation nodes in the correct order. + sortNodes(); + + int numSortedNodes = mSortedNodes.size(); + for (int i = 0; i < numSortedNodes; ++i) { + Node node = mSortedNodes.get(i); + // First, clear out the old listeners + ArrayList oldListeners = node.animation.getListeners(); + if (oldListeners != null && oldListeners.size() > 0) { + final ArrayList clonedListeners = new + ArrayList(oldListeners); + + for (AnimatorListener listener : clonedListeners) { + if (listener instanceof DependencyListener || + listener instanceof AnimatorSetListener) { + node.animation.removeListener(listener); + } + } + } + } + + // nodesToStart holds the list of nodes to be started immediately. We don't want to + // start the animations in the loop directly because we first need to set up + // dependencies on all of the nodes. For example, we don't want to start an animation + // when some other animation also wants to start when the first animation begins. + final ArrayList nodesToStart = new ArrayList(); + for (int i = 0; i < numSortedNodes; ++i) { + Node node = mSortedNodes.get(i); + if (mSetListener == null) { + mSetListener = new AnimatorSetListener(this); + } + if (node.dependencies == null || node.dependencies.size() == 0) { + nodesToStart.add(node); + } else { + int numDependencies = node.dependencies.size(); + for (int j = 0; j < numDependencies; ++j) { + Dependency dependency = node.dependencies.get(j); + dependency.node.animation.addListener( + new DependencyListener(this, node, dependency.rule)); + } + node.tmpDependencies = (ArrayList) node.dependencies.clone(); + } + node.animation.addListener(mSetListener); + } + // Now that all dependencies are set up, start the animations that should be started. + if (mStartDelay <= 0) { + for (Node node : nodesToStart) { + node.animation.start(); + mPlayingSet.add(node.animation); + } + } else { + mDelayAnim = ValueAnimator.ofFloat(0f, 1f); + mDelayAnim.setDuration(mStartDelay); + mDelayAnim.addListener(new AnimatorListenerAdapter() { + boolean canceled = false; + public void onAnimationCancel(Animator anim) { + canceled = true; + } + public void onAnimationEnd(Animator anim) { + if (!canceled) { + int numNodes = nodesToStart.size(); + for (int i = 0; i < numNodes; ++i) { + Node node = nodesToStart.get(i); + node.animation.start(); + mPlayingSet.add(node.animation); + } + } + } + }); + mDelayAnim.start(); + } + if (mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationStart(this); + } + } + if (mNodes.size() == 0 && mStartDelay == 0) { + // Handle unusual case where empty AnimatorSet is started - should send out + // end event immediately since the event will not be sent out at all otherwise + mStarted = false; + if (mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationEnd(this); + } + } + } + } + + @Override + public AnimatorSet clone() { + final AnimatorSet anim = (AnimatorSet) super.clone(); + /* + * The basic clone() operation copies all items. This doesn't work very well for + * AnimatorSet, because it will copy references that need to be recreated and state + * that may not apply. What we need to do now is put the clone in an uninitialized + * state, with fresh, empty data structures. Then we will build up the nodes list + * manually, as we clone each Node (and its animation). The clone will then be sorted, + * and will populate any appropriate lists, when it is started. + */ + anim.mNeedsSort = true; + anim.mTerminated = false; + anim.mStarted = false; + anim.mPlayingSet = new ArrayList(); + anim.mNodeMap = new HashMap(); + anim.mNodes = new ArrayList(); + anim.mSortedNodes = new ArrayList(); + + // Walk through the old nodes list, cloning each node and adding it to the new nodemap. + // One problem is that the old node dependencies point to nodes in the old AnimatorSet. + // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. + HashMap nodeCloneMap = new HashMap(); // + for (Node node : mNodes) { + Node nodeClone = node.clone(); + nodeCloneMap.put(node, nodeClone); + anim.mNodes.add(nodeClone); + anim.mNodeMap.put(nodeClone.animation, nodeClone); + // Clear out the dependencies in the clone; we'll set these up manually later + nodeClone.dependencies = null; + nodeClone.tmpDependencies = null; + nodeClone.nodeDependents = null; + nodeClone.nodeDependencies = null; + // clear out any listeners that were set up by the AnimatorSet; these will + // be set up when the clone's nodes are sorted + ArrayList cloneListeners = nodeClone.animation.getListeners(); + if (cloneListeners != null) { + ArrayList listenersToRemove = null; + for (AnimatorListener listener : cloneListeners) { + if (listener instanceof AnimatorSetListener) { + if (listenersToRemove == null) { + listenersToRemove = new ArrayList(); + } + listenersToRemove.add(listener); + } + } + if (listenersToRemove != null) { + for (AnimatorListener listener : listenersToRemove) { + cloneListeners.remove(listener); + } + } + } + } + // Now that we've cloned all of the nodes, we're ready to walk through their + // dependencies, mapping the old dependencies to the new nodes + for (Node node : mNodes) { + Node nodeClone = nodeCloneMap.get(node); + if (node.dependencies != null) { + for (Dependency dependency : node.dependencies) { + Node clonedDependencyNode = nodeCloneMap.get(dependency.node); + Dependency cloneDependency = new Dependency(clonedDependencyNode, + dependency.rule); + nodeClone.addDependency(cloneDependency); + } + } + } + + return anim; + } + + /** + * This class is the mechanism by which animations are started based on events in other + * animations. If an animation has multiple dependencies on other animations, then + * all dependencies must be satisfied before the animation is started. + */ + private static class DependencyListener implements AnimatorListener { + + private AnimatorSet mAnimatorSet; + + // The node upon which the dependency is based. + private Node mNode; + + // The Dependency rule (WITH or AFTER) that the listener should wait for on + // the node + private int mRule; + + public DependencyListener(AnimatorSet animatorSet, Node node, int rule) { + this.mAnimatorSet = animatorSet; + this.mNode = node; + this.mRule = rule; + } + + /** + * Ignore cancel events for now. We may want to handle this eventually, + * to prevent follow-on animations from running when some dependency + * animation is canceled. + */ + public void onAnimationCancel(Animator animation) { + } + + /** + * An end event is received - see if this is an event we are listening for + */ + public void onAnimationEnd(Animator animation) { + if (mRule == Dependency.AFTER) { + startIfReady(animation); + } + } + + /** + * Ignore repeat events for now + */ + public void onAnimationRepeat(Animator animation) { + } + + /** + * A start event is received - see if this is an event we are listening for + */ + public void onAnimationStart(Animator animation) { + if (mRule == Dependency.WITH) { + startIfReady(animation); + } + } + + /** + * Check whether the event received is one that the node was waiting for. + * If so, mark it as complete and see whether it's time to start + * the animation. + * @param dependencyAnimation the animation that sent the event. + */ + private void startIfReady(Animator dependencyAnimation) { + if (mAnimatorSet.mTerminated) { + // if the parent AnimatorSet was canceled, then don't start any dependent anims + return; + } + Dependency dependencyToRemove = null; + int numDependencies = mNode.tmpDependencies.size(); + for (int i = 0; i < numDependencies; ++i) { + Dependency dependency = mNode.tmpDependencies.get(i); + if (dependency.rule == mRule && + dependency.node.animation == dependencyAnimation) { + // rule fired - remove the dependency and listener and check to + // see whether it's time to start the animation + dependencyToRemove = dependency; + dependencyAnimation.removeListener(this); + break; + } + } + mNode.tmpDependencies.remove(dependencyToRemove); + if (mNode.tmpDependencies.size() == 0) { + // all dependencies satisfied: start the animation + mNode.animation.start(); + mAnimatorSet.mPlayingSet.add(mNode.animation); + } + } + + } + + private class AnimatorSetListener implements AnimatorListener { + + private AnimatorSet mAnimatorSet; + + AnimatorSetListener(AnimatorSet animatorSet) { + mAnimatorSet = animatorSet; + } + + public void onAnimationCancel(Animator animation) { + if (!mTerminated) { + // Listeners are already notified of the AnimatorSet canceling in cancel(). + // The logic below only kicks in when animations end normally + if (mPlayingSet.size() == 0) { + if (mListeners != null) { + int numListeners = mListeners.size(); + for (int i = 0; i < numListeners; ++i) { + mListeners.get(i).onAnimationCancel(mAnimatorSet); + } + } + } + } + } + + public void onAnimationEnd(Animator animation) { + animation.removeListener(this); + mPlayingSet.remove(animation); + Node animNode = mAnimatorSet.mNodeMap.get(animation); + animNode.done = true; + if (!mTerminated) { + // Listeners are already notified of the AnimatorSet ending in cancel() or + // end(); the logic below only kicks in when animations end normally + ArrayList sortedNodes = mAnimatorSet.mSortedNodes; + boolean allDone = true; + int numSortedNodes = sortedNodes.size(); + for (int i = 0; i < numSortedNodes; ++i) { + if (!sortedNodes.get(i).done) { + allDone = false; + break; + } + } + if (allDone) { + // If this was the last child animation to end, then notify listeners that this + // AnimatorSet has ended + if (mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationEnd(mAnimatorSet); + } + } + mAnimatorSet.mStarted = false; + } + } + } + + // Nothing to do + public void onAnimationRepeat(Animator animation) { + } + + // Nothing to do + public void onAnimationStart(Animator animation) { + } + + } + + /** + * This method sorts the current set of nodes, if needed. The sort is a simple + * DependencyGraph sort, which goes like this: + * - All nodes without dependencies become 'roots' + * - while roots list is not null + * - for each root r + * - add r to sorted list + * - remove r as a dependency from any other node + * - any nodes with no dependencies are added to the roots list + */ + private void sortNodes() { + if (mNeedsSort) { + mSortedNodes.clear(); + ArrayList roots = new ArrayList(); + int numNodes = mNodes.size(); + for (int i = 0; i < numNodes; ++i) { + Node node = mNodes.get(i); + if (node.dependencies == null || node.dependencies.size() == 0) { + roots.add(node); + } + } + ArrayList tmpRoots = new ArrayList(); + while (roots.size() > 0) { + int numRoots = roots.size(); + for (int i = 0; i < numRoots; ++i) { + Node root = roots.get(i); + mSortedNodes.add(root); + if (root.nodeDependents != null) { + int numDependents = root.nodeDependents.size(); + for (int j = 0; j < numDependents; ++j) { + Node node = root.nodeDependents.get(j); + node.nodeDependencies.remove(root); + if (node.nodeDependencies.size() == 0) { + tmpRoots.add(node); + } + } + } + } + roots.clear(); + roots.addAll(tmpRoots); + tmpRoots.clear(); + } + mNeedsSort = false; + if (mSortedNodes.size() != mNodes.size()) { + throw new IllegalStateException("Circular dependencies cannot exist" + + " in AnimatorSet"); + } + } else { + // Doesn't need sorting, but still need to add in the nodeDependencies list + // because these get removed as the event listeners fire and the dependencies + // are satisfied + int numNodes = mNodes.size(); + for (int i = 0; i < numNodes; ++i) { + Node node = mNodes.get(i); + if (node.dependencies != null && node.dependencies.size() > 0) { + int numDependencies = node.dependencies.size(); + for (int j = 0; j < numDependencies; ++j) { + Dependency dependency = node.dependencies.get(j); + if (node.nodeDependencies == null) { + node.nodeDependencies = new ArrayList(); + } + if (!node.nodeDependencies.contains(dependency.node)) { + node.nodeDependencies.add(dependency.node); + } + } + } + // nodes are 'done' by default; they become un-done when started, and done + // again when ended + node.done = false; + } + } + } + + /** + * Dependency holds information about the node that some other node is + * dependent upon and the nature of that dependency. + * + */ + private static class Dependency { + static final int WITH = 0; // dependent node must start with this dependency node + static final int AFTER = 1; // dependent node must start when this dependency node finishes + + // The node that the other node with this Dependency is dependent upon + public Node node; + + // The nature of the dependency (WITH or AFTER) + public int rule; + + public Dependency(Node node, int rule) { + this.node = node; + this.rule = rule; + } + } + + /** + * A Node is an embodiment of both the Animator that it wraps as well as + * any dependencies that are associated with that Animation. This includes + * both dependencies upon other nodes (in the dependencies list) as + * well as dependencies of other nodes upon this (in the nodeDependents list). + */ + private static class Node implements Cloneable { + public Animator animation; + + /** + * These are the dependencies that this node's animation has on other + * nodes. For example, if this node's animation should begin with some + * other animation ends, then there will be an item in this node's + * dependencies list for that other animation's node. + */ + public ArrayList dependencies = null; + + /** + * tmpDependencies is a runtime detail. We use the dependencies list for sorting. + * But we also use the list to keep track of when multiple dependencies are satisfied, + * but removing each dependency as it is satisfied. We do not want to remove + * the dependency itself from the list, because we need to retain that information + * if the AnimatorSet is launched in the future. So we create a copy of the dependency + * list when the AnimatorSet starts and use this tmpDependencies list to track the + * list of satisfied dependencies. + */ + public ArrayList tmpDependencies = null; + + /** + * nodeDependencies is just a list of the nodes that this Node is dependent upon. + * This information is used in sortNodes(), to determine when a node is a root. + */ + public ArrayList nodeDependencies = null; + + /** + * nodeDepdendents is the list of nodes that have this node as a dependency. This + * is a utility field used in sortNodes to facilitate removing this node as a + * dependency when it is a root node. + */ + public ArrayList nodeDependents = null; + + /** + * Flag indicating whether the animation in this node is finished. This flag + * is used by AnimatorSet to check, as each animation ends, whether all child animations + * are done and it's time to send out an end event for the entire AnimatorSet. + */ + public boolean done = false; + + /** + * Constructs the Node with the animation that it encapsulates. A Node has no + * dependencies by default; dependencies are added via the addDependency() + * method. + * + * @param animation The animation that the Node encapsulates. + */ + public Node(Animator animation) { + this.animation = animation; + } + + /** + * Add a dependency to this Node. The dependency includes information about the + * node that this node is dependency upon and the nature of the dependency. + * @param dependency + */ + public void addDependency(Dependency dependency) { + if (dependencies == null) { + dependencies = new ArrayList(); + nodeDependencies = new ArrayList(); + } + dependencies.add(dependency); + if (!nodeDependencies.contains(dependency.node)) { + nodeDependencies.add(dependency.node); + } + Node dependencyNode = dependency.node; + if (dependencyNode.nodeDependents == null) { + dependencyNode.nodeDependents = new ArrayList(); + } + dependencyNode.nodeDependents.add(this); + } + + @Override + public Node clone() { + try { + Node node = (Node) super.clone(); + node.animation = animation.clone(); + return node; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + } + + /** + * The Builder object is a utility class to facilitate adding animations to a + * AnimatorSet along with the relationships between the various animations. The + * intention of the Builder methods, along with the {@link + * AnimatorSet#play(Animator) play()} method of AnimatorSet is to make it possible + * to express the dependency relationships of animations in a natural way. Developers can also + * use the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link + * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need, + * but it might be easier in some situations to express the AnimatorSet of animations in pairs. + *

+ *

The Builder object cannot be constructed directly, but is rather constructed + * internally via a call to {@link AnimatorSet#play(Animator)}.

+ *

+ *

For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to + * play when anim2 finishes, and anim4 to play when anim3 finishes:

+ *
+     *     AnimatorSet s = new AnimatorSet();
+     *     s.play(anim1).with(anim2);
+     *     s.play(anim2).before(anim3);
+     *     s.play(anim4).after(anim3);
+     * 
+ *

+ *

Note in the example that both {@link Builder#before(Animator)} and {@link + * Builder#after(Animator)} are used. These are just different ways of expressing the same + * relationship and are provided to make it easier to say things in a way that is more natural, + * depending on the situation.

+ *

+ *

It is possible to make several calls into the same Builder object to express + * multiple relationships. However, note that it is only the animation passed into the initial + * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive + * calls to the Builder object. For example, the following code starts both anim2 + * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and + * anim3: + *

+     *   AnimatorSet s = new AnimatorSet();
+     *   s.play(anim1).before(anim2).before(anim3);
+     * 
+ * If the desired result is to play anim1 then anim2 then anim3, this code expresses the + * relationship correctly:

+ *
+     *   AnimatorSet s = new AnimatorSet();
+     *   s.play(anim1).before(anim2);
+     *   s.play(anim2).before(anim3);
+     * 
+ *

+ *

Note that it is possible to express relationships that cannot be resolved and will not + * result in sensible results. For example, play(anim1).after(anim1) makes no + * sense. In general, circular dependencies like this one (or more indirect ones where a depends + * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets + * that can boil down to a simple, one-way relationship of animations starting with, before, and + * after other, different, animations.

+ */ + public class Builder { + + /** + * This tracks the current node being processed. It is supplied to the play() method + * of AnimatorSet and passed into the constructor of Builder. + */ + private Node mCurrentNode; + + /** + * package-private constructor. Builders are only constructed by AnimatorSet, when the + * play() method is called. + * + * @param anim The animation that is the dependency for the other animations passed into + * the other methods of this Builder object. + */ + Builder(Animator anim) { + mCurrentNode = mNodeMap.get(anim); + if (mCurrentNode == null) { + mCurrentNode = new Node(anim); + mNodeMap.put(anim, mCurrentNode); + mNodes.add(mCurrentNode); + } + } + + /** + * Sets up the given animation to play at the same time as the animation supplied in the + * {@link AnimatorSet#play(Animator)} call that created this Builder object. + * + * @param anim The animation that will play when the animation supplied to the + * {@link AnimatorSet#play(Animator)} method starts. + */ + public Builder with(Animator anim) { + Node node = mNodeMap.get(anim); + if (node == null) { + node = new Node(anim); + mNodeMap.put(anim, node); + mNodes.add(node); + } + Dependency dependency = new Dependency(mCurrentNode, Dependency.WITH); + node.addDependency(dependency); + return this; + } + + /** + * Sets up the given animation to play when the animation supplied in the + * {@link AnimatorSet#play(Animator)} call that created this Builder object + * ends. + * + * @param anim The animation that will play when the animation supplied to the + * {@link AnimatorSet#play(Animator)} method ends. + */ + public Builder before(Animator anim) { + Node node = mNodeMap.get(anim); + if (node == null) { + node = new Node(anim); + mNodeMap.put(anim, node); + mNodes.add(node); + } + Dependency dependency = new Dependency(mCurrentNode, Dependency.AFTER); + node.addDependency(dependency); + return this; + } + + /** + * Sets up the given animation to play when the animation supplied in the + * {@link AnimatorSet#play(Animator)} call that created this Builder object + * to start when the animation supplied in this method call ends. + * + * @param anim The animation whose end will cause the animation supplied to the + * {@link AnimatorSet#play(Animator)} method to play. + */ + public Builder after(Animator anim) { + Node node = mNodeMap.get(anim); + if (node == null) { + node = new Node(anim); + mNodeMap.put(anim, node); + mNodes.add(node); + } + Dependency dependency = new Dependency(node, Dependency.AFTER); + mCurrentNode.addDependency(dependency); + return this; + } + + /** + * Sets up the animation supplied in the + * {@link AnimatorSet#play(Animator)} call that created this Builder object + * to play when the given amount of time elapses. + * + * @param delay The number of milliseconds that should elapse before the + * animation starts. + */ + public Builder after(long delay) { + // setup dummy ValueAnimator just to run the clock + ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f); + anim.setDuration(delay); + after(anim); + return this; + } + + } + +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java new file mode 100644 index 000000000..e41019364 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +/** + * This evaluator can be used to perform type interpolation between float values. + */ +public class FloatEvaluator implements TypeEvaluator { + + /** + * This function returns the result of linearly interpolating the start and end values, with + * fraction representing the proportion between the start and end values. The + * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), + * where x0 is startValue, x1 is endValue, + * and t is fraction. + * + * @param fraction The fraction from the starting to the ending values + * @param startValue The start value; should be of type float or + * Float + * @param endValue The end value; should be of type float or Float + * @return A linear interpolation between the start and end values, given the + * fraction parameter. + */ + public Float evaluate(float fraction, Number startValue, Number endValue) { + float startFloat = startValue.floatValue(); + return startFloat + fraction * (endValue.floatValue() - startFloat); + } +} \ No newline at end of file diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java new file mode 100644 index 000000000..6d9dafa7a --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import java.util.ArrayList; +import android.view.animation.Interpolator; + +import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.FloatKeyframe; + +/** + * This class holds a collection of FloatKeyframe objects and is called by ValueAnimator to calculate + * values between those keyframes for a given animation. The class internal to the animation + * package because it is an implementation detail of how Keyframes are stored and used. + * + *

This type-specific subclass of KeyframeSet, along with the other type-specific subclass for + * int, exists to speed up the getValue() method when there is no custom + * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the + * Object equivalents of these primitive types.

+ */ +@SuppressWarnings("unchecked") +class FloatKeyframeSet extends KeyframeSet { + private float firstValue; + private float lastValue; + private float deltaValue; + private boolean firstTime = true; + + public FloatKeyframeSet(FloatKeyframe... keyframes) { + super(keyframes); + } + + @Override + public Object getValue(float fraction) { + return getFloatValue(fraction); + } + + @Override + public FloatKeyframeSet clone() { + ArrayList keyframes = mKeyframes; + int numKeyframes = mKeyframes.size(); + FloatKeyframe[] newKeyframes = new FloatKeyframe[numKeyframes]; + for (int i = 0; i < numKeyframes; ++i) { + newKeyframes[i] = (FloatKeyframe) keyframes.get(i).clone(); + } + FloatKeyframeSet newSet = new FloatKeyframeSet(newKeyframes); + return newSet; + } + + public float getFloatValue(float fraction) { + if (mNumKeyframes == 2) { + if (firstTime) { + firstTime = false; + firstValue = ((FloatKeyframe) mKeyframes.get(0)).getFloatValue(); + lastValue = ((FloatKeyframe) mKeyframes.get(1)).getFloatValue(); + deltaValue = lastValue - firstValue; + } + if (mInterpolator != null) { + fraction = mInterpolator.getInterpolation(fraction); + } + if (mEvaluator == null) { + return firstValue + fraction * deltaValue; + } else { + return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).floatValue(); + } + } + if (fraction <= 0f) { + final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0); + final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(1); + float prevValue = prevKeyframe.getFloatValue(); + float nextValue = nextKeyframe.getFloatValue(); + float prevFraction = prevKeyframe.getFraction(); + float nextFraction = nextKeyframe.getFraction(); + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + intervalFraction * (nextValue - prevValue) : + ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). + floatValue(); + } else if (fraction >= 1f) { + final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 2); + final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 1); + float prevValue = prevKeyframe.getFloatValue(); + float nextValue = nextKeyframe.getFloatValue(); + float prevFraction = prevKeyframe.getFraction(); + float nextFraction = nextKeyframe.getFraction(); + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + intervalFraction * (nextValue - prevValue) : + ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). + floatValue(); + } + FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0); + for (int i = 1; i < mNumKeyframes; ++i) { + FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(i); + if (fraction < nextKeyframe.getFraction()) { + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevKeyframe.getFraction()) / + (nextKeyframe.getFraction() - prevKeyframe.getFraction()); + float prevValue = prevKeyframe.getFloatValue(); + float nextValue = nextKeyframe.getFloatValue(); + return mEvaluator == null ? + prevValue + intervalFraction * (nextValue - prevValue) : + ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). + floatValue(); + } + prevKeyframe = nextKeyframe; + } + // shouldn't get here + return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).floatValue(); + } + +} + diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java new file mode 100644 index 000000000..ed5e79ec6 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +/** + * This evaluator can be used to perform type interpolation between int values. + */ +public class IntEvaluator implements TypeEvaluator { + + /** + * This function returns the result of linearly interpolating the start and end values, with + * fraction representing the proportion between the start and end values. The + * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), + * where x0 is startValue, x1 is endValue, + * and t is fraction. + * + * @param fraction The fraction from the starting to the ending values + * @param startValue The start value; should be of type int or + * Integer + * @param endValue The end value; should be of type int or Integer + * @return A linear interpolation between the start and end values, given the + * fraction parameter. + */ + public Integer evaluate(float fraction, Integer startValue, Integer endValue) { + int startInt = startValue; + return (int)(startInt + fraction * (endValue - startInt)); + } +} \ No newline at end of file diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java new file mode 100644 index 000000000..e9215e7f8 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import java.util.ArrayList; +import android.view.animation.Interpolator; + +import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.IntKeyframe; + +/** + * This class holds a collection of IntKeyframe objects and is called by ValueAnimator to calculate + * values between those keyframes for a given animation. The class internal to the animation + * package because it is an implementation detail of how Keyframes are stored and used. + * + *

This type-specific subclass of KeyframeSet, along with the other type-specific subclass for + * float, exists to speed up the getValue() method when there is no custom + * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the + * Object equivalents of these primitive types.

+ */ +@SuppressWarnings("unchecked") +class IntKeyframeSet extends KeyframeSet { + private int firstValue; + private int lastValue; + private int deltaValue; + private boolean firstTime = true; + + public IntKeyframeSet(IntKeyframe... keyframes) { + super(keyframes); + } + + @Override + public Object getValue(float fraction) { + return getIntValue(fraction); + } + + @Override + public IntKeyframeSet clone() { + ArrayList keyframes = mKeyframes; + int numKeyframes = mKeyframes.size(); + IntKeyframe[] newKeyframes = new IntKeyframe[numKeyframes]; + for (int i = 0; i < numKeyframes; ++i) { + newKeyframes[i] = (IntKeyframe) keyframes.get(i).clone(); + } + IntKeyframeSet newSet = new IntKeyframeSet(newKeyframes); + return newSet; + } + + public int getIntValue(float fraction) { + if (mNumKeyframes == 2) { + if (firstTime) { + firstTime = false; + firstValue = ((IntKeyframe) mKeyframes.get(0)).getIntValue(); + lastValue = ((IntKeyframe) mKeyframes.get(1)).getIntValue(); + deltaValue = lastValue - firstValue; + } + if (mInterpolator != null) { + fraction = mInterpolator.getInterpolation(fraction); + } + if (mEvaluator == null) { + return firstValue + (int)(fraction * deltaValue); + } else { + return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).intValue(); + } + } + if (fraction <= 0f) { + final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0); + final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(1); + int prevValue = prevKeyframe.getIntValue(); + int nextValue = nextKeyframe.getIntValue(); + float prevFraction = prevKeyframe.getFraction(); + float nextFraction = nextKeyframe.getFraction(); + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + (int)(intervalFraction * (nextValue - prevValue)) : + ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). + intValue(); + } else if (fraction >= 1f) { + final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 2); + final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 1); + int prevValue = prevKeyframe.getIntValue(); + int nextValue = nextKeyframe.getIntValue(); + float prevFraction = prevKeyframe.getFraction(); + float nextFraction = nextKeyframe.getFraction(); + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + (int)(intervalFraction * (nextValue - prevValue)) : + ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).intValue(); + } + IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0); + for (int i = 1; i < mNumKeyframes; ++i) { + IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(i); + if (fraction < nextKeyframe.getFraction()) { + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevKeyframe.getFraction()) / + (nextKeyframe.getFraction() - prevKeyframe.getFraction()); + int prevValue = prevKeyframe.getIntValue(); + int nextValue = nextKeyframe.getIntValue(); + return mEvaluator == null ? + prevValue + (int)(intervalFraction * (nextValue - prevValue)) : + ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)). + intValue(); + } + prevKeyframe = nextKeyframe; + } + // shouldn't get here + return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).intValue(); + } + +} + diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java new file mode 100644 index 000000000..ab76fa7f6 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import android.view.animation.Interpolator; + +/** + * This class holds a time/value pair for an animation. The Keyframe class is used + * by {@link ValueAnimator} to define the values that the animation target will have over the course + * of the animation. As the time proceeds from one keyframe to the other, the value of the + * target object will animate between the value at the previous keyframe and the value at the + * next keyframe. Each keyframe also holds an optional {@link TimeInterpolator} + * object, which defines the time interpolation over the intervalue preceding the keyframe. + * + *

The Keyframe class itself is abstract. The type-specific factory methods will return + * a subclass of Keyframe specific to the type of value being stored. This is done to improve + * performance when dealing with the most common cases (e.g., float and + * int values). Other types will fall into a more general Keyframe class that + * treats its values as Objects. Unless your animation requires dealing with a custom type + * or a data structure that needs to be animated directly (and evaluated using an implementation + * of {@link TypeEvaluator}), you should stick to using float and int as animations using those + * types have lower runtime overhead than other types.

+ */ +@SuppressWarnings("rawtypes") +public abstract class Keyframe implements Cloneable { + /** + * The time at which mValue will hold true. + */ + float mFraction; + + /** + * The type of the value in this Keyframe. This type is determined at construction time, + * based on the type of the value object passed into the constructor. + */ + Class mValueType; + + /** + * The optional time interpolator for the interval preceding this keyframe. A null interpolator + * (the default) results in linear interpolation over the interval. + */ + private /*Time*/Interpolator mInterpolator = null; + + /** + * Flag to indicate whether this keyframe has a valid value. This flag is used when an + * animation first starts, to populate placeholder keyframes with real values derived + * from the target object. + */ + boolean mHasValue = false; + + /** + * Constructs a Keyframe object with the given time and value. The time defines the + * time, as a proportion of an overall animation's duration, at which the value will hold true + * for the animation. The value for the animation between keyframes will be calculated as + * an interpolation between the values at those keyframes. + * + * @param fraction The time, expressed as a value between 0 and 1, representing the fraction + * of time elapsed of the overall animation duration. + * @param value The value that the object will animate to as the animation time approaches + * the time in this keyframe, and the the value animated from as the time passes the time in + * this keyframe. + */ + public static Keyframe ofInt(float fraction, int value) { + return new IntKeyframe(fraction, value); + } + + /** + * Constructs a Keyframe object with the given time. The value at this time will be derived + * from the target object when the animation first starts (note that this implies that keyframes + * with no initial value must be used as part of an {@link ObjectAnimator}). + * The time defines the + * time, as a proportion of an overall animation's duration, at which the value will hold true + * for the animation. The value for the animation between keyframes will be calculated as + * an interpolation between the values at those keyframes. + * + * @param fraction The time, expressed as a value between 0 and 1, representing the fraction + * of time elapsed of the overall animation duration. + */ + public static Keyframe ofInt(float fraction) { + return new IntKeyframe(fraction); + } + + /** + * Constructs a Keyframe object with the given time and value. The time defines the + * time, as a proportion of an overall animation's duration, at which the value will hold true + * for the animation. The value for the animation between keyframes will be calculated as + * an interpolation between the values at those keyframes. + * + * @param fraction The time, expressed as a value between 0 and 1, representing the fraction + * of time elapsed of the overall animation duration. + * @param value The value that the object will animate to as the animation time approaches + * the time in this keyframe, and the the value animated from as the time passes the time in + * this keyframe. + */ + public static Keyframe ofFloat(float fraction, float value) { + return new FloatKeyframe(fraction, value); + } + + /** + * Constructs a Keyframe object with the given time. The value at this time will be derived + * from the target object when the animation first starts (note that this implies that keyframes + * with no initial value must be used as part of an {@link ObjectAnimator}). + * The time defines the + * time, as a proportion of an overall animation's duration, at which the value will hold true + * for the animation. The value for the animation between keyframes will be calculated as + * an interpolation between the values at those keyframes. + * + * @param fraction The time, expressed as a value between 0 and 1, representing the fraction + * of time elapsed of the overall animation duration. + */ + public static Keyframe ofFloat(float fraction) { + return new FloatKeyframe(fraction); + } + + /** + * Constructs a Keyframe object with the given time and value. The time defines the + * time, as a proportion of an overall animation's duration, at which the value will hold true + * for the animation. The value for the animation between keyframes will be calculated as + * an interpolation between the values at those keyframes. + * + * @param fraction The time, expressed as a value between 0 and 1, representing the fraction + * of time elapsed of the overall animation duration. + * @param value The value that the object will animate to as the animation time approaches + * the time in this keyframe, and the the value animated from as the time passes the time in + * this keyframe. + */ + public static Keyframe ofObject(float fraction, Object value) { + return new ObjectKeyframe(fraction, value); + } + + /** + * Constructs a Keyframe object with the given time. The value at this time will be derived + * from the target object when the animation first starts (note that this implies that keyframes + * with no initial value must be used as part of an {@link ObjectAnimator}). + * The time defines the + * time, as a proportion of an overall animation's duration, at which the value will hold true + * for the animation. The value for the animation between keyframes will be calculated as + * an interpolation between the values at those keyframes. + * + * @param fraction The time, expressed as a value between 0 and 1, representing the fraction + * of time elapsed of the overall animation duration. + */ + public static Keyframe ofObject(float fraction) { + return new ObjectKeyframe(fraction, null); + } + + /** + * Indicates whether this keyframe has a valid value. This method is called internally when + * an {@link ObjectAnimator} first starts; keyframes without values are assigned values at + * that time by deriving the value for the property from the target object. + * + * @return boolean Whether this object has a value assigned. + */ + public boolean hasValue() { + return mHasValue; + } + + /** + * Gets the value for this Keyframe. + * + * @return The value for this Keyframe. + */ + public abstract Object getValue(); + + /** + * Sets the value for this Keyframe. + * + * @param value value for this Keyframe. + */ + public abstract void setValue(Object value); + + /** + * Gets the time for this keyframe, as a fraction of the overall animation duration. + * + * @return The time associated with this keyframe, as a fraction of the overall animation + * duration. This should be a value between 0 and 1. + */ + public float getFraction() { + return mFraction; + } + + /** + * Sets the time for this keyframe, as a fraction of the overall animation duration. + * + * @param fraction time associated with this keyframe, as a fraction of the overall animation + * duration. This should be a value between 0 and 1. + */ + public void setFraction(float fraction) { + mFraction = fraction; + } + + /** + * Gets the optional interpolator for this Keyframe. A value of null indicates + * that there is no interpolation, which is the same as linear interpolation. + * + * @return The optional interpolator for this Keyframe. + */ + public /*Time*/Interpolator getInterpolator() { + return mInterpolator; + } + + /** + * Sets the optional interpolator for this Keyframe. A value of null indicates + * that there is no interpolation, which is the same as linear interpolation. + * + * @return The optional interpolator for this Keyframe. + */ + public void setInterpolator(/*Time*/Interpolator interpolator) { + mInterpolator = interpolator; + } + + /** + * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of + * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based + * on the type of Keyframe created. + * + * @return The type of the value stored in the Keyframe. + */ + public Class getType() { + return mValueType; + } + + @Override + public abstract Keyframe clone(); + + /** + * This internal subclass is used for all types which are not int or float. + */ + static class ObjectKeyframe extends Keyframe { + + /** + * The value of the animation at the time mFraction. + */ + Object mValue; + + ObjectKeyframe(float fraction, Object value) { + mFraction = fraction; + mValue = value; + mHasValue = (value != null); + mValueType = mHasValue ? value.getClass() : Object.class; + } + + public Object getValue() { + return mValue; + } + + public void setValue(Object value) { + mValue = value; + mHasValue = (value != null); + } + + @Override + public ObjectKeyframe clone() { + ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mValue); + kfClone.setInterpolator(getInterpolator()); + return kfClone; + } + } + + /** + * Internal subclass used when the keyframe value is of type int. + */ + static class IntKeyframe extends Keyframe { + + /** + * The value of the animation at the time mFraction. + */ + int mValue; + + IntKeyframe(float fraction, int value) { + mFraction = fraction; + mValue = value; + mValueType = int.class; + mHasValue = true; + } + + IntKeyframe(float fraction) { + mFraction = fraction; + mValueType = int.class; + } + + public int getIntValue() { + return mValue; + } + + public Object getValue() { + return mValue; + } + + public void setValue(Object value) { + if (value != null && value.getClass() == Integer.class) { + mValue = ((Integer)value).intValue(); + mHasValue = true; + } + } + + @Override + public IntKeyframe clone() { + IntKeyframe kfClone = new IntKeyframe(getFraction(), mValue); + kfClone.setInterpolator(getInterpolator()); + return kfClone; + } + } + + /** + * Internal subclass used when the keyframe value is of type float. + */ + static class FloatKeyframe extends Keyframe { + /** + * The value of the animation at the time mFraction. + */ + float mValue; + + FloatKeyframe(float fraction, float value) { + mFraction = fraction; + mValue = value; + mValueType = float.class; + mHasValue = true; + } + + FloatKeyframe(float fraction) { + mFraction = fraction; + mValueType = float.class; + } + + public float getFloatValue() { + return mValue; + } + + public Object getValue() { + return mValue; + } + + public void setValue(Object value) { + if (value != null && value.getClass() == Float.class) { + mValue = ((Float)value).floatValue(); + mHasValue = true; + } + } + + @Override + public FloatKeyframe clone() { + FloatKeyframe kfClone = new FloatKeyframe(getFraction(), mValue); + kfClone.setInterpolator(getInterpolator()); + return kfClone; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java new file mode 100644 index 000000000..a71e1ad3c --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import java.util.ArrayList; +import java.util.Arrays; +import android.view.animation.Interpolator; + +import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.FloatKeyframe; +import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.IntKeyframe; +import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.ObjectKeyframe; + +/** + * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate + * values between those keyframes for a given animation. The class internal to the animation + * package because it is an implementation detail of how Keyframes are stored and used. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +class KeyframeSet { + + int mNumKeyframes; + + Keyframe mFirstKeyframe; + Keyframe mLastKeyframe; + /*Time*/Interpolator mInterpolator; // only used in the 2-keyframe case + ArrayList mKeyframes; // only used when there are not 2 keyframes + TypeEvaluator mEvaluator; + + + public KeyframeSet(Keyframe... keyframes) { + mNumKeyframes = keyframes.length; + mKeyframes = new ArrayList(); + mKeyframes.addAll(Arrays.asList(keyframes)); + mFirstKeyframe = mKeyframes.get(0); + mLastKeyframe = mKeyframes.get(mNumKeyframes - 1); + mInterpolator = mLastKeyframe.getInterpolator(); + } + + public static KeyframeSet ofInt(int... values) { + int numKeyframes = values.length; + IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)]; + if (numKeyframes == 1) { + keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f); + keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]); + } else { + keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]); + for (int i = 1; i < numKeyframes; ++i) { + keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]); + } + } + return new IntKeyframeSet(keyframes); + } + + public static KeyframeSet ofFloat(float... values) { + int numKeyframes = values.length; + FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)]; + if (numKeyframes == 1) { + keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f); + keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]); + } else { + keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]); + for (int i = 1; i < numKeyframes; ++i) { + keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]); + } + } + return new FloatKeyframeSet(keyframes); + } + + public static KeyframeSet ofKeyframe(Keyframe... keyframes) { + // if all keyframes of same primitive type, create the appropriate KeyframeSet + int numKeyframes = keyframes.length; + boolean hasFloat = false; + boolean hasInt = false; + boolean hasOther = false; + for (int i = 0; i < numKeyframes; ++i) { + if (keyframes[i] instanceof FloatKeyframe) { + hasFloat = true; + } else if (keyframes[i] instanceof IntKeyframe) { + hasInt = true; + } else { + hasOther = true; + } + } + if (hasFloat && !hasInt && !hasOther) { + FloatKeyframe floatKeyframes[] = new FloatKeyframe[numKeyframes]; + for (int i = 0; i < numKeyframes; ++i) { + floatKeyframes[i] = (FloatKeyframe) keyframes[i]; + } + return new FloatKeyframeSet(floatKeyframes); + } else if (hasInt && !hasFloat && !hasOther) { + IntKeyframe intKeyframes[] = new IntKeyframe[numKeyframes]; + for (int i = 0; i < numKeyframes; ++i) { + intKeyframes[i] = (IntKeyframe) keyframes[i]; + } + return new IntKeyframeSet(intKeyframes); + } else { + return new KeyframeSet(keyframes); + } + } + + public static KeyframeSet ofObject(Object... values) { + int numKeyframes = values.length; + ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,2)]; + if (numKeyframes == 1) { + keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f); + keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]); + } else { + keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]); + for (int i = 1; i < numKeyframes; ++i) { + keyframes[i] = (ObjectKeyframe) Keyframe.ofObject((float) i / (numKeyframes - 1), values[i]); + } + } + return new KeyframeSet(keyframes); + } + + /** + * Sets the TypeEvaluator to be used when calculating animated values. This object + * is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet, + * both of which assume their own evaluator to speed up calculations with those primitive + * types. + * + * @param evaluator The TypeEvaluator to be used to calculate animated values. + */ + public void setEvaluator(TypeEvaluator evaluator) { + mEvaluator = evaluator; + } + + @Override + public KeyframeSet clone() { + ArrayList keyframes = mKeyframes; + int numKeyframes = mKeyframes.size(); + Keyframe[] newKeyframes = new Keyframe[numKeyframes]; + for (int i = 0; i < numKeyframes; ++i) { + newKeyframes[i] = keyframes.get(i).clone(); + } + KeyframeSet newSet = new KeyframeSet(newKeyframes); + return newSet; + } + + /** + * Gets the animated value, given the elapsed fraction of the animation (interpolated by the + * animation's interpolator) and the evaluator used to calculate in-between values. This + * function maps the input fraction to the appropriate keyframe interval and a fraction + * between them and returns the interpolated value. Note that the input fraction may fall + * outside the [0-1] bounds, if the animation's interpolator made that happen (e.g., a + * spring interpolation that might send the fraction past 1.0). We handle this situation by + * just using the two keyframes at the appropriate end when the value is outside those bounds. + * + * @param fraction The elapsed fraction of the animation + * @return The animated value. + */ + public Object getValue(float fraction) { + + // Special-case optimization for the common case of only two keyframes + if (mNumKeyframes == 2) { + if (mInterpolator != null) { + fraction = mInterpolator.getInterpolation(fraction); + } + return mEvaluator.evaluate(fraction, mFirstKeyframe.getValue(), + mLastKeyframe.getValue()); + } + if (fraction <= 0f) { + final Keyframe nextKeyframe = mKeyframes.get(1); + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + final float prevFraction = mFirstKeyframe.getFraction(); + float intervalFraction = (fraction - prevFraction) / + (nextKeyframe.getFraction() - prevFraction); + return mEvaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(), + nextKeyframe.getValue()); + } else if (fraction >= 1f) { + final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2); + final /*Time*/Interpolator interpolator = mLastKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + final float prevFraction = prevKeyframe.getFraction(); + float intervalFraction = (fraction - prevFraction) / + (mLastKeyframe.getFraction() - prevFraction); + return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(), + mLastKeyframe.getValue()); + } + Keyframe prevKeyframe = mFirstKeyframe; + for (int i = 1; i < mNumKeyframes; ++i) { + Keyframe nextKeyframe = mKeyframes.get(i); + if (fraction < nextKeyframe.getFraction()) { + final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + final float prevFraction = prevKeyframe.getFraction(); + float intervalFraction = (fraction - prevFraction) / + (nextKeyframe.getFraction() - prevFraction); + return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(), + nextKeyframe.getValue()); + } + prevKeyframe = nextKeyframe; + } + // shouldn't reach here + return mLastKeyframe.getValue(); + } + + @Override + public String toString() { + String returnVal = " "; + for (int i = 0; i < mNumKeyframes; ++i) { + returnVal += mKeyframes.get(i).getValue() + " "; + } + return returnVal; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java new file mode 100644 index 000000000..21d15c02a --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import android.util.Log; +//import android.util.Property; + +//import java.lang.reflect.Method; +import java.util.ArrayList; + +/** + * This subclass of {@link ValueAnimator} provides support for animating properties on target objects. + * The constructors of this class take parameters to define the target object that will be animated + * as well as the name of the property that will be animated. Appropriate set/get functions + * are then determined internally and the animation will call these functions as necessary to + * animate the property. + * + * @see #setPropertyName(String) + * + */ +@SuppressWarnings("rawtypes") +public final class ObjectAnimator extends ValueAnimator { + private static final boolean DBG = false; + + // The target object on which the property exists, set in the constructor + private Object mTarget; + + private String mPropertyName; + + //private Property mProperty; + + /** + * Sets the name of the property that will be animated. This name is used to derive + * a setter function that will be called to set animated values. + * For example, a property name of foo will result + * in a call to the function setFoo() on the target object. If either + * valueFrom or valueTo is null, then a getter function will + * also be derived and called. + * + *

For best performance of the mechanism that calls the setter function determined by the + * name of the property being animated, use float or int typed values, + * and make the setter function for those properties have a void return value. This + * will cause the code to take an optimized path for these constrained circumstances. Other + * property types and return types will work, but will have more overhead in processing + * the requests due to normal reflection mechanisms.

+ * + *

Note that the setter function derived from this property name + * must take the same parameter type as the + * valueFrom and valueTo properties, otherwise the call to + * the setter function will fail.

+ * + *

If this ObjectAnimator has been set up to animate several properties together, + * using more than one PropertyValuesHolder objects, then setting the propertyName simply + * sets the propertyName in the first of those PropertyValuesHolder objects.

+ * + * @param propertyName The name of the property being animated. Should not be null. + */ + public void setPropertyName(String propertyName) { + // mValues could be null if this is being constructed piecemeal. Just record the + // propertyName to be used later when setValues() is called if so. + if (mValues != null) { + PropertyValuesHolder valuesHolder = mValues[0]; + String oldName = valuesHolder.getPropertyName(); + valuesHolder.setPropertyName(propertyName); + mValuesMap.remove(oldName); + mValuesMap.put(propertyName, valuesHolder); + } + mPropertyName = propertyName; + // New property/values/target should cause re-initialization prior to starting + mInitialized = false; + } + + /** + * Sets the property that will be animated. Property objects will take precedence over + * properties specified by the {@link #setPropertyName(String)} method. Animations should + * be set up to use one or the other, not both. + * + * @param property The property being animated. Should not be null. + */ + //public void setProperty(Property property) { + // // mValues could be null if this is being constructed piecemeal. Just record the + // // propertyName to be used later when setValues() is called if so. + // if (mValues != null) { + // PropertyValuesHolder valuesHolder = mValues[0]; + // String oldName = valuesHolder.getPropertyName(); + // valuesHolder.setProperty(property); + // mValuesMap.remove(oldName); + // mValuesMap.put(mPropertyName, valuesHolder); + // } + // if (mProperty != null) { + // mPropertyName = property.getName(); + // } + // mProperty = property; + // // New property/values/target should cause re-initialization prior to starting + // mInitialized = false; + //} + + /** + * Gets the name of the property that will be animated. This name will be used to derive + * a setter function that will be called to set animated values. + * For example, a property name of foo will result + * in a call to the function setFoo() on the target object. If either + * valueFrom or valueTo is null, then a getter function will + * also be derived and called. + */ + public String getPropertyName() { + return mPropertyName; + } + + /** + * Creates a new ObjectAnimator object. This default constructor is primarily for + * use internally; the other constructors which take parameters are more generally + * useful. + */ + public ObjectAnimator() { + } + + /** + * Private utility constructor that initializes the target object and name of the + * property being animated. + * + * @param target The object whose property is to be animated. This object should + * have a public method on it called setName(), where name is + * the value of the propertyName parameter. + * @param propertyName The name of the property being animated. + */ + private ObjectAnimator(Object target, String propertyName) { + mTarget = target; + setPropertyName(propertyName); + } + + /** + * Private utility constructor that initializes the target object and property being animated. + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + */ + //private ObjectAnimator(T target, Property property) { + // mTarget = target; + // setProperty(property); + //} + + /** + * Constructs and returns an ObjectAnimator that animates between int values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. This object should + * have a public method on it called setName(), where name is + * the value of the propertyName parameter. + * @param propertyName The name of the property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofInt(Object target, String propertyName, int... values) { + ObjectAnimator anim = new ObjectAnimator(target, propertyName); + anim.setIntValues(values); + return anim; + } + + /** + * Constructs and returns an ObjectAnimator that animates between int values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + //public static ObjectAnimator ofInt(T target, Property property, int... values) { + // ObjectAnimator anim = new ObjectAnimator(target, property); + // anim.setIntValues(values); + // return anim; + //} + + /** + * Constructs and returns an ObjectAnimator that animates between float values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. This object should + * have a public method on it called setName(), where name is + * the value of the propertyName parameter. + * @param propertyName The name of the property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { + ObjectAnimator anim = new ObjectAnimator(target, propertyName); + anim.setFloatValues(values); + return anim; + } + + /** + * Constructs and returns an ObjectAnimator that animates between float values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + //public static ObjectAnimator ofFloat(T target, Property property, + // float... values) { + // ObjectAnimator anim = new ObjectAnimator(target, property); + // anim.setFloatValues(values); + // return anim; + //} + + /** + * Constructs and returns an ObjectAnimator that animates between Object values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. This object should + * have a public method on it called setName(), where name is + * the value of the propertyName parameter. + * @param propertyName The name of the property being animated. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofObject(Object target, String propertyName, + TypeEvaluator evaluator, Object... values) { + ObjectAnimator anim = new ObjectAnimator(target, propertyName); + anim.setObjectValues(values); + anim.setEvaluator(evaluator); + return anim; + } + + /** + * Constructs and returns an ObjectAnimator that animates between Object values. A single + * value implies that that value is the one being animated to. Two values imply a starting + * and ending values. More than two values imply a starting value, values to animate through + * along the way, and an ending value (these values will be distributed evenly across + * the duration of the animation). + * + * @param target The object whose property is to be animated. + * @param property The property being animated. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + //public static ObjectAnimator ofObject(T target, Property property, + // TypeEvaluator evaluator, V... values) { + // ObjectAnimator anim = new ObjectAnimator(target, property); + // anim.setObjectValues(values); + // anim.setEvaluator(evaluator); + // return anim; + //} + + /** + * Constructs and returns an ObjectAnimator that animates between the sets of values specified + * in PropertyValueHolder objects. This variant should be used when animating + * several properties at once with the same ObjectAnimator, since PropertyValuesHolder allows + * you to associate a set of animation values with a property name. + * + * @param target The object whose property is to be animated. Depending on how the + * PropertyValuesObjects were constructed, the target object should either have the {@link + * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the + * PropertyValuesHOlder objects were created with property names) the target object should have + * public methods on it called setName(), where name is the name of + * the property passed in as the propertyName parameter for each of the + * PropertyValuesHolder objects. + * @param values A set of PropertyValuesHolder objects whose values will be animated between + * over time. + * @return An ObjectAnimator object that is set up to animate between the given values. + */ + public static ObjectAnimator ofPropertyValuesHolder(Object target, + PropertyValuesHolder... values) { + ObjectAnimator anim = new ObjectAnimator(); + anim.mTarget = target; + anim.setValues(values); + return anim; + } + + @Override + public void setIntValues(int... values) { + if (mValues == null || mValues.length == 0) { + // No values yet - this animator is being constructed piecemeal. Init the values with + // whatever the current propertyName is + //if (mProperty != null) { + // setValues(PropertyValuesHolder.ofInt(mProperty, values)); + //} else { + setValues(PropertyValuesHolder.ofInt(mPropertyName, values)); + //} + } else { + super.setIntValues(values); + } + } + + @Override + public void setFloatValues(float... values) { + if (mValues == null || mValues.length == 0) { + // No values yet - this animator is being constructed piecemeal. Init the values with + // whatever the current propertyName is + //if (mProperty != null) { + // setValues(PropertyValuesHolder.ofFloat(mProperty, values)); + //} else { + setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); + //} + } else { + super.setFloatValues(values); + } + } + + @Override + public void setObjectValues(Object... values) { + if (mValues == null || mValues.length == 0) { + // No values yet - this animator is being constructed piecemeal. Init the values with + // whatever the current propertyName is + //if (mProperty != null) { + // setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator)null, values)); + //} else { + setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values)); + //} + } else { + super.setObjectValues(values); + } + } + + @Override + public void start() { + if (DBG) { + Log.d("ObjectAnimator", "Anim target, duration: " + mTarget + ", " + getDuration()); + for (int i = 0; i < mValues.length; ++i) { + PropertyValuesHolder pvh = mValues[i]; + ArrayList keyframes = pvh.mKeyframeSet.mKeyframes; + Log.d("ObjectAnimator", " Values[" + i + "]: " + + pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " + + keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue()); + } + } + super.start(); + } + + /** + * This function is called immediately before processing the first animation + * frame of an animation. If there is a nonzero startDelay, the + * function is called after that delay ends. + * It takes care of the final initialization steps for the + * animation. This includes setting mEvaluator, if the user has not yet + * set it up, and the setter/getter methods, if the user did not supply + * them. + * + *

Overriders of this method should call the superclass method to cause + * internal mechanisms to be set up correctly.

+ */ + @Override + void initAnimation() { + if (!mInitialized) { + // mValueType may change due to setter/getter setup; do this before calling super.init(), + // which uses mValueType to set up the default type evaluator. + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupSetterAndGetter(mTarget); + } + super.initAnimation(); + } + } + + /** + * Sets the length of the animation. The default duration is 300 milliseconds. + * + * @param duration The length of the animation, in milliseconds. + * @return ObjectAnimator The object called with setDuration(). This return + * value makes it easier to compose statements together that construct and then set the + * duration, as in + * ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start(). + */ + @Override + public ObjectAnimator setDuration(long duration) { + super.setDuration(duration); + return this; + } + + + /** + * The target object whose property will be animated by this animation + * + * @return The object being animated + */ + public Object getTarget() { + return mTarget; + } + + /** + * Sets the target object whose property will be animated by this animation + * + * @param target The object being animated + */ + @Override + public void setTarget(Object target) { + if (mTarget != target) { + final Object oldTarget = mTarget; + mTarget = target; + if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) { + return; + } + // New target type should cause re-initialization prior to starting + mInitialized = false; + } + } + + @Override + public void setupStartValues() { + initAnimation(); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupStartValue(mTarget); + } + } + + @Override + public void setupEndValues() { + initAnimation(); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupEndValue(mTarget); + } + } + + /** + * This method is called with the elapsed fraction of the animation during every + * animation frame. This function turns the elapsed fraction into an interpolated fraction + * and then into an animated value (from the evaluator. The function is called mostly during + * animation updates, but it is also called when the end() + * function is called, to set the final value on the property. + * + *

Overrides of this method must call the superclass to perform the calculation + * of the animated value.

+ * + * @param fraction The elapsed fraction of the animation. + */ + @Override + void animateValue(float fraction) { + super.animateValue(fraction); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setAnimatedValue(mTarget); + } + } + + @Override + public ObjectAnimator clone() { + final ObjectAnimator anim = (ObjectAnimator) super.clone(); + return anim; + } + + @Override + public String toString() { + String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " + + mTarget; + if (mValues != null) { + for (int i = 0; i < mValues.length; ++i) { + returnVal += "\n " + mValues[i].toString(); + } + } + return returnVal; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java new file mode 100644 index 000000000..84f7504ab --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java @@ -0,0 +1,1012 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +//import android.util.FloatProperty; +//import android.util.IntProperty; +import android.util.Log; +//import android.util.Property; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * This class holds information about a property and the values that that property + * should take on during an animation. PropertyValuesHolder objects can be used to create + * animations with ValueAnimator or ObjectAnimator that operate on several different properties + * in parallel. + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class PropertyValuesHolder implements Cloneable { + + /** + * The name of the property associated with the values. This need not be a real property, + * unless this object is being used with ObjectAnimator. But this is the name by which + * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator. + */ + String mPropertyName; + + /** + * @hide + */ + //protected Property mProperty; + + /** + * The setter function, if needed. ObjectAnimator hands off this functionality to + * PropertyValuesHolder, since it holds all of the per-property information. This + * property is automatically + * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. + */ + Method mSetter = null; + + /** + * The getter function, if needed. ObjectAnimator hands off this functionality to + * PropertyValuesHolder, since it holds all of the per-property information. This + * property is automatically + * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. + * The getter is only derived and used if one of the values is null. + */ + private Method mGetter = null; + + /** + * The type of values supplied. This information is used both in deriving the setter/getter + * functions and in deriving the type of TypeEvaluator. + */ + Class mValueType; + + /** + * The set of keyframes (time/value pairs) that define this animation. + */ + KeyframeSet mKeyframeSet = null; + + + // type evaluators for the primitive types handled by this implementation + private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); + private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); + + // We try several different types when searching for appropriate setter/getter functions. + // The caller may have supplied values in a type that does not match the setter/getter + // functions (such as the integers 0 and 1 to represent floating point values for alpha). + // Also, the use of generics in constructors means that we end up with the Object versions + // of primitive types (Float vs. float). But most likely, the setter/getter functions + // will take primitive types instead. + // So we supply an ordered array of other types to try before giving up. + private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class, + Double.class, Integer.class}; + private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class, + Float.class, Double.class}; + private static Class[] DOUBLE_VARIANTS = {double.class, Double.class, float.class, int.class, + Float.class, Integer.class}; + + // These maps hold all property entries for a particular class. This map + // is used to speed up property/setter/getter lookups for a given class/property + // combination. No need to use reflection on the combination more than once. + private static final HashMap> sSetterPropertyMap = + new HashMap>(); + private static final HashMap> sGetterPropertyMap = + new HashMap>(); + + // This lock is used to ensure that only one thread is accessing the property maps + // at a time. + final ReentrantReadWriteLock mPropertyMapLock = new ReentrantReadWriteLock(); + + // Used to pass single value to varargs parameter in setter invocation + final Object[] mTmpValueArray = new Object[1]; + + /** + * The type evaluator used to calculate the animated values. This evaluator is determined + * automatically based on the type of the start/end objects passed into the constructor, + * but the system only knows about the primitive types int and float. Any other + * type will need to set the evaluator to a custom evaluator for that type. + */ + private TypeEvaluator mEvaluator; + + /** + * The value most recently calculated by calculateValue(). This is set during + * that function and might be retrieved later either by ValueAnimator.animatedValue() or + * by the property-setting logic in ObjectAnimator.animatedValue(). + */ + private Object mAnimatedValue; + + /** + * Internal utility constructor, used by the factory methods to set the property name. + * @param propertyName The name of the property for this holder. + */ + private PropertyValuesHolder(String propertyName) { + mPropertyName = propertyName; + } + + /** + * Internal utility constructor, used by the factory methods to set the property. + * @param property The property for this holder. + */ + //private PropertyValuesHolder(Property property) { + // mProperty = property; + // if (property != null) { + // mPropertyName = property.getName(); + // } + //} + + /** + * Constructs and returns a PropertyValuesHolder with a given property name and + * set of int values. + * @param propertyName The name of the property being animated. + * @param values The values that the named property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static PropertyValuesHolder ofInt(String propertyName, int... values) { + return new IntPropertyValuesHolder(propertyName, values); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of int values. + * @param property The property being animated. Should not be null. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + //public static PropertyValuesHolder ofInt(Property property, int... values) { + // return new IntPropertyValuesHolder(property, values); + //} + + /** + * Constructs and returns a PropertyValuesHolder with a given property name and + * set of float values. + * @param propertyName The name of the property being animated. + * @param values The values that the named property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static PropertyValuesHolder ofFloat(String propertyName, float... values) { + return new FloatPropertyValuesHolder(propertyName, values); + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of float values. + * @param property The property being animated. Should not be null. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + //public static PropertyValuesHolder ofFloat(Property property, float... values) { + // return new FloatPropertyValuesHolder(property, values); + //} + + /** + * Constructs and returns a PropertyValuesHolder with a given property name and + * set of Object values. This variant also takes a TypeEvaluator because the system + * cannot automatically interpolate between objects of unknown type. + * + * @param propertyName The name of the property being animated. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values The values that the named property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator, + Object... values) { + PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); + pvh.setObjectValues(values); + pvh.setEvaluator(evaluator); + return pvh; + } + + /** + * Constructs and returns a PropertyValuesHolder with a given property and + * set of Object values. This variant also takes a TypeEvaluator because the system + * cannot automatically interpolate between objects of unknown type. + * + * @param property The property being animated. Should not be null. + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the necessary interpolation between the Object values to derive the animated + * value. + * @param values The values that the property will animate between. + * @return PropertyValuesHolder The constructed PropertyValuesHolder object. + */ + //public static PropertyValuesHolder ofObject(Property property, + // TypeEvaluator evaluator, V... values) { + // PropertyValuesHolder pvh = new PropertyValuesHolder(property); + // pvh.setObjectValues(values); + // pvh.setEvaluator(evaluator); + // return pvh; + //} + + /** + * Constructs and returns a PropertyValuesHolder object with the specified property name and set + * of values. These values can be of any type, but the type should be consistent so that + * an appropriate {@link android.animation.TypeEvaluator} can be found that matches + * the common type. + *

If there is only one value, it is assumed to be the end value of an animation, + * and an initial value will be derived, if possible, by calling a getter function + * on the object. Also, if any value is null, the value will be filled in when the animation + * starts in the same way. This mechanism of automatically getting null values only works + * if the PropertyValuesHolder object is used in conjunction + * {@link ObjectAnimator}, and with a getter function + * derived automatically from propertyName, since otherwise PropertyValuesHolder has + * no way of determining what the value should be. + * @param propertyName The name of the property associated with this set of values. This + * can be the actual property name to be used when using a ObjectAnimator object, or + * just a name used to get animated values, such as if this object is used with an + * ValueAnimator object. + * @param values The set of values to animate between. + */ + public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) { + KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); + if (keyframeSet instanceof IntKeyframeSet) { + return new IntPropertyValuesHolder(propertyName, (IntKeyframeSet) keyframeSet); + } else if (keyframeSet instanceof FloatKeyframeSet) { + return new FloatPropertyValuesHolder(propertyName, (FloatKeyframeSet) keyframeSet); + } + else { + PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); + pvh.mKeyframeSet = keyframeSet; + pvh.mValueType = values[0].getType(); + return pvh; + } + } + + /** + * Constructs and returns a PropertyValuesHolder object with the specified property and set + * of values. These values can be of any type, but the type should be consistent so that + * an appropriate {@link android.animation.TypeEvaluator} can be found that matches + * the common type. + *

If there is only one value, it is assumed to be the end value of an animation, + * and an initial value will be derived, if possible, by calling the property's + * {@link android.util.Property#get(Object)} function. + * Also, if any value is null, the value will be filled in when the animation + * starts in the same way. This mechanism of automatically getting null values only works + * if the PropertyValuesHolder object is used in conjunction with + * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has + * no way of determining what the value should be. + * @param property The property associated with this set of values. Should not be null. + * @param values The set of values to animate between. + */ + //public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) { + // KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values); + // if (keyframeSet instanceof IntKeyframeSet) { + // return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet); + // } else if (keyframeSet instanceof FloatKeyframeSet) { + // return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet); + // } + // else { + // PropertyValuesHolder pvh = new PropertyValuesHolder(property); + // pvh.mKeyframeSet = keyframeSet; + // pvh.mValueType = ((Keyframe)values[0]).getType(); + // return pvh; + // } + //} + + /** + * Set the animated values for this object to this set of ints. + * If there is only one value, it is assumed to be the end value of an animation, + * and an initial value will be derived, if possible, by calling a getter function + * on the object. Also, if any value is null, the value will be filled in when the animation + * starts in the same way. This mechanism of automatically getting null values only works + * if the PropertyValuesHolder object is used in conjunction + * {@link ObjectAnimator}, and with a getter function + * derived automatically from propertyName, since otherwise PropertyValuesHolder has + * no way of determining what the value should be. + * + * @param values One or more values that the animation will animate between. + */ + public void setIntValues(int... values) { + mValueType = int.class; + mKeyframeSet = KeyframeSet.ofInt(values); + } + + /** + * Set the animated values for this object to this set of floats. + * If there is only one value, it is assumed to be the end value of an animation, + * and an initial value will be derived, if possible, by calling a getter function + * on the object. Also, if any value is null, the value will be filled in when the animation + * starts in the same way. This mechanism of automatically getting null values only works + * if the PropertyValuesHolder object is used in conjunction + * {@link ObjectAnimator}, and with a getter function + * derived automatically from propertyName, since otherwise PropertyValuesHolder has + * no way of determining what the value should be. + * + * @param values One or more values that the animation will animate between. + */ + public void setFloatValues(float... values) { + mValueType = float.class; + mKeyframeSet = KeyframeSet.ofFloat(values); + } + + /** + * Set the animated values for this object to this set of Keyframes. + * + * @param values One or more values that the animation will animate between. + */ + public void setKeyframes(Keyframe... values) { + int numKeyframes = values.length; + Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; + mValueType = values[0].getType(); + for (int i = 0; i < numKeyframes; ++i) { + keyframes[i] = values[i]; + } + mKeyframeSet = new KeyframeSet(keyframes); + } + + /** + * Set the animated values for this object to this set of Objects. + * If there is only one value, it is assumed to be the end value of an animation, + * and an initial value will be derived, if possible, by calling a getter function + * on the object. Also, if any value is null, the value will be filled in when the animation + * starts in the same way. This mechanism of automatically getting null values only works + * if the PropertyValuesHolder object is used in conjunction + * {@link ObjectAnimator}, and with a getter function + * derived automatically from propertyName, since otherwise PropertyValuesHolder has + * no way of determining what the value should be. + * + * @param values One or more values that the animation will animate between. + */ + public void setObjectValues(Object... values) { + mValueType = values[0].getClass(); + mKeyframeSet = KeyframeSet.ofObject(values); + } + + /** + * Determine the setter or getter function using the JavaBeans convention of setFoo or + * getFoo for a property named 'foo'. This function figures out what the name of the + * function should be and uses reflection to find the Method with that name on the + * target object. + * + * @param targetClass The class to search for the method + * @param prefix "set" or "get", depending on whether we need a setter or getter. + * @param valueType The type of the parameter (in the case of a setter). This type + * is derived from the values set on this PropertyValuesHolder. This type is used as + * a first guess at the parameter type, but we check for methods with several different + * types to avoid problems with slight mis-matches between supplied values and actual + * value types used on the setter. + * @return Method the method associated with mPropertyName. + */ + private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) { + // TODO: faster implementation... + Method returnVal = null; + String methodName = getMethodName(prefix, mPropertyName); + Class args[] = null; + if (valueType == null) { + try { + returnVal = targetClass.getMethod(methodName, args); + } catch (NoSuchMethodException e) { + Log.e("PropertyValuesHolder", targetClass.getSimpleName() + " - " + + "Couldn't find no-arg method for property " + mPropertyName + ": " + e); + } + } else { + args = new Class[1]; + Class typeVariants[]; + if (mValueType.equals(Float.class)) { + typeVariants = FLOAT_VARIANTS; + } else if (mValueType.equals(Integer.class)) { + typeVariants = INTEGER_VARIANTS; + } else if (mValueType.equals(Double.class)) { + typeVariants = DOUBLE_VARIANTS; + } else { + typeVariants = new Class[1]; + typeVariants[0] = mValueType; + } + for (Class typeVariant : typeVariants) { + args[0] = typeVariant; + try { + returnVal = targetClass.getMethod(methodName, args); + // change the value type to suit + mValueType = typeVariant; + return returnVal; + } catch (NoSuchMethodException e) { + // Swallow the error and keep trying other variants + } + } + // If we got here, then no appropriate function was found + Log.e("PropertyValuesHolder", + "Couldn't find " + prefix + "ter property " + mPropertyName + + " for " + targetClass.getSimpleName() + + " with value type "+ mValueType); + } + + return returnVal; + } + + + /** + * Returns the setter or getter requested. This utility function checks whether the + * requested method exists in the propertyMapMap cache. If not, it calls another + * utility function to request the Method from the targetClass directly. + * @param targetClass The Class on which the requested method should exist. + * @param propertyMapMap The cache of setters/getters derived so far. + * @param prefix "set" or "get", for the setter or getter. + * @param valueType The type of parameter passed into the method (null for getter). + * @return Method the method associated with mPropertyName. + */ + private Method setupSetterOrGetter(Class targetClass, + HashMap> propertyMapMap, + String prefix, Class valueType) { + Method setterOrGetter = null; + try { + // Have to lock property map prior to reading it, to guard against + // another thread putting something in there after we've checked it + // but before we've added an entry to it + mPropertyMapLock.writeLock().lock(); + HashMap propertyMap = propertyMapMap.get(targetClass); + if (propertyMap != null) { + setterOrGetter = propertyMap.get(mPropertyName); + } + if (setterOrGetter == null) { + setterOrGetter = getPropertyFunction(targetClass, prefix, valueType); + if (propertyMap == null) { + propertyMap = new HashMap(); + propertyMapMap.put(targetClass, propertyMap); + } + propertyMap.put(mPropertyName, setterOrGetter); + } + } finally { + mPropertyMapLock.writeLock().unlock(); + } + return setterOrGetter; + } + + /** + * Utility function to get the setter from targetClass + * @param targetClass The Class on which the requested method should exist. + */ + void setupSetter(Class targetClass) { + mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", mValueType); + } + + /** + * Utility function to get the getter from targetClass + */ + private void setupGetter(Class targetClass) { + mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null); + } + + /** + * Internal function (called from ObjectAnimator) to set up the setter and getter + * prior to running the animation. If the setter has not been manually set for this + * object, it will be derived automatically given the property name, target object, and + * types of values supplied. If no getter has been set, it will be supplied iff any of the + * supplied values was null. If there is a null value, then the getter (supplied or derived) + * will be called to set those null values to the current value of the property + * on the target object. + * @param target The object on which the setter (and possibly getter) exist. + */ + void setupSetterAndGetter(Object target) { + //if (mProperty != null) { + // // check to make sure that mProperty is on the class of target + // try { + // Object testValue = mProperty.get(target); + // for (Keyframe kf : mKeyframeSet.mKeyframes) { + // if (!kf.hasValue()) { + // kf.setValue(mProperty.get(target)); + // } + // } + // return; + // } catch (ClassCastException e) { + // Log.e("PropertyValuesHolder","No such property (" + mProperty.getName() + + // ") on target object " + target + ". Trying reflection instead"); + // mProperty = null; + // } + //} + Class targetClass = target.getClass(); + if (mSetter == null) { + setupSetter(targetClass); + } + for (Keyframe kf : mKeyframeSet.mKeyframes) { + if (!kf.hasValue()) { + if (mGetter == null) { + setupGetter(targetClass); + } + try { + kf.setValue(mGetter.invoke(target)); + } catch (InvocationTargetException e) { + Log.e("PropertyValuesHolder", e.toString()); + } catch (IllegalAccessException e) { + Log.e("PropertyValuesHolder", e.toString()); + } + } + } + } + + /** + * Utility function to set the value stored in a particular Keyframe. The value used is + * whatever the value is for the property name specified in the keyframe on the target object. + * + * @param target The target object from which the current value should be extracted. + * @param kf The keyframe which holds the property name and value. + */ + private void setupValue(Object target, Keyframe kf) { + //if (mProperty != null) { + // kf.setValue(mProperty.get(target)); + //} + try { + if (mGetter == null) { + Class targetClass = target.getClass(); + setupGetter(targetClass); + } + kf.setValue(mGetter.invoke(target)); + } catch (InvocationTargetException e) { + Log.e("PropertyValuesHolder", e.toString()); + } catch (IllegalAccessException e) { + Log.e("PropertyValuesHolder", e.toString()); + } + } + + /** + * This function is called by ObjectAnimator when setting the start values for an animation. + * The start values are set according to the current values in the target object. The + * property whose value is extracted is whatever is specified by the propertyName of this + * PropertyValuesHolder object. + * + * @param target The object which holds the start values that should be set. + */ + void setupStartValue(Object target) { + setupValue(target, mKeyframeSet.mKeyframes.get(0)); + } + + /** + * This function is called by ObjectAnimator when setting the end values for an animation. + * The end values are set according to the current values in the target object. The + * property whose value is extracted is whatever is specified by the propertyName of this + * PropertyValuesHolder object. + * + * @param target The object which holds the start values that should be set. + */ + void setupEndValue(Object target) { + setupValue(target, mKeyframeSet.mKeyframes.get(mKeyframeSet.mKeyframes.size() - 1)); + } + + @Override + public PropertyValuesHolder clone() { + try { + PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); + newPVH.mPropertyName = mPropertyName; + //newPVH.mProperty = mProperty; + newPVH.mKeyframeSet = mKeyframeSet.clone(); + newPVH.mEvaluator = mEvaluator; + return newPVH; + } catch (CloneNotSupportedException e) { + // won't reach here + return null; + } + } + + /** + * Internal function to set the value on the target object, using the setter set up + * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator + * to handle turning the value calculated by ValueAnimator into a value set on the object + * according to the name of the property. + * @param target The target object on which the value is set + */ + void setAnimatedValue(Object target) { + //if (mProperty != null) { + // mProperty.set(target, getAnimatedValue()); + //} + if (mSetter != null) { + try { + mTmpValueArray[0] = getAnimatedValue(); + mSetter.invoke(target, mTmpValueArray); + } catch (InvocationTargetException e) { + Log.e("PropertyValuesHolder", e.toString()); + } catch (IllegalAccessException e) { + Log.e("PropertyValuesHolder", e.toString()); + } + } + } + + /** + * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used + * to calculate animated values. + */ + void init() { + if (mEvaluator == null) { + // We already handle int and float automatically, but not their Object + // equivalents + mEvaluator = (mValueType == Integer.class) ? sIntEvaluator : + (mValueType == Float.class) ? sFloatEvaluator : + null; + } + if (mEvaluator != null) { + // KeyframeSet knows how to evaluate the common types - only give it a custom + // evaluator if one has been set on this class + mKeyframeSet.setEvaluator(mEvaluator); + } + } + + /** + * The TypeEvaluator will the automatically determined based on the type of values + * supplied to PropertyValuesHolder. The evaluator can be manually set, however, if so + * desired. This may be important in cases where either the type of the values supplied + * do not match the way that they should be interpolated between, or if the values + * are of a custom type or one not currently understood by the animation system. Currently, + * only values of type float and int (and their Object equivalents: Float + * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator. + * @param evaluator + */ + public void setEvaluator(TypeEvaluator evaluator) { + mEvaluator = evaluator; + mKeyframeSet.setEvaluator(evaluator); + } + + /** + * Function used to calculate the value according to the evaluator set up for + * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue(). + * + * @param fraction The elapsed, interpolated fraction of the animation. + */ + void calculateValue(float fraction) { + mAnimatedValue = mKeyframeSet.getValue(fraction); + } + + /** + * Sets the name of the property that will be animated. This name is used to derive + * a setter function that will be called to set animated values. + * For example, a property name of foo will result + * in a call to the function setFoo() on the target object. If either + * valueFrom or valueTo is null, then a getter function will + * also be derived and called. + * + *

Note that the setter function derived from this property name + * must take the same parameter type as the + * valueFrom and valueTo properties, otherwise the call to + * the setter function will fail.

+ * + * @param propertyName The name of the property being animated. + */ + public void setPropertyName(String propertyName) { + mPropertyName = propertyName; + } + + /** + * Sets the property that will be animated. + * + *

Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property + * must exist on the target object specified in that ObjectAnimator.

+ * + * @param property The property being animated. + */ + //public void setProperty(Property property) { + // mProperty = property; + //} + + /** + * Gets the name of the property that will be animated. This name will be used to derive + * a setter function that will be called to set animated values. + * For example, a property name of foo will result + * in a call to the function setFoo() on the target object. If either + * valueFrom or valueTo is null, then a getter function will + * also be derived and called. + */ + public String getPropertyName() { + return mPropertyName; + } + + /** + * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value + * most recently calculated in calculateValue(). + * @return + */ + Object getAnimatedValue() { + return mAnimatedValue; + } + + @Override + public String toString() { + return mPropertyName + ": " + mKeyframeSet.toString(); + } + + /** + * Utility method to derive a setter/getter method name from a property name, where the + * prefix is typically "set" or "get" and the first letter of the property name is + * capitalized. + * + * @param prefix The precursor to the method name, before the property name begins, typically + * "set" or "get". + * @param propertyName The name of the property that represents the bulk of the method name + * after the prefix. The first letter of this word will be capitalized in the resulting + * method name. + * @return String the property name converted to a method name according to the conventions + * specified above. + */ + static String getMethodName(String prefix, String propertyName) { + if (propertyName == null || propertyName.length() == 0) { + // shouldn't get here + return prefix; + } + char firstLetter = Character.toUpperCase(propertyName.charAt(0)); + String theRest = propertyName.substring(1); + return prefix + firstLetter + theRest; + } + + static class IntPropertyValuesHolder extends PropertyValuesHolder { + + // Cache JNI functions to avoid looking them up twice + //private static final HashMap> sJNISetterPropertyMap = + // new HashMap>(); + //int mJniSetter; + //private IntProperty mIntProperty; + + IntKeyframeSet mIntKeyframeSet; + int mIntAnimatedValue; + + public IntPropertyValuesHolder(String propertyName, IntKeyframeSet keyframeSet) { + super(propertyName); + mValueType = int.class; + mKeyframeSet = keyframeSet; + mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + } + + //public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) { + // super(property); + // mValueType = int.class; + // mKeyframeSet = keyframeSet; + // mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + // if (property instanceof IntProperty) { + // mIntProperty = (IntProperty) mProperty; + // } + //} + + public IntPropertyValuesHolder(String propertyName, int... values) { + super(propertyName); + setIntValues(values); + } + + //public IntPropertyValuesHolder(Property property, int... values) { + // super(property); + // setIntValues(values); + // if (property instanceof IntProperty) { + // mIntProperty = (IntProperty) mProperty; + // } + //} + + @Override + public void setIntValues(int... values) { + super.setIntValues(values); + mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + } + + @Override + void calculateValue(float fraction) { + mIntAnimatedValue = mIntKeyframeSet.getIntValue(fraction); + } + + @Override + Object getAnimatedValue() { + return mIntAnimatedValue; + } + + @Override + public IntPropertyValuesHolder clone() { + IntPropertyValuesHolder newPVH = (IntPropertyValuesHolder) super.clone(); + newPVH.mIntKeyframeSet = (IntKeyframeSet) newPVH.mKeyframeSet; + return newPVH; + } + + /** + * Internal function to set the value on the target object, using the setter set up + * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator + * to handle turning the value calculated by ValueAnimator into a value set on the object + * according to the name of the property. + * @param target The target object on which the value is set + */ + @Override + void setAnimatedValue(Object target) { + //if (mIntProperty != null) { + // mIntProperty.setValue(target, mIntAnimatedValue); + // return; + //} + //if (mProperty != null) { + // mProperty.set(target, mIntAnimatedValue); + // return; + //} + //if (mJniSetter != 0) { + // nCallIntMethod(target, mJniSetter, mIntAnimatedValue); + // return; + //} + if (mSetter != null) { + try { + mTmpValueArray[0] = mIntAnimatedValue; + mSetter.invoke(target, mTmpValueArray); + } catch (InvocationTargetException e) { + Log.e("PropertyValuesHolder", e.toString()); + } catch (IllegalAccessException e) { + Log.e("PropertyValuesHolder", e.toString()); + } + } + } + + @Override + void setupSetter(Class targetClass) { + //if (mProperty != null) { + // return; + //} + // Check new static hashmap for setter method + //try { + // mPropertyMapLock.writeLock().lock(); + // HashMap propertyMap = sJNISetterPropertyMap.get(targetClass); + // if (propertyMap != null) { + // Integer mJniSetterInteger = propertyMap.get(mPropertyName); + // if (mJniSetterInteger != null) { + // mJniSetter = mJniSetterInteger; + // } + // } + // if (mJniSetter == 0) { + // String methodName = getMethodName("set", mPropertyName); + // mJniSetter = nGetIntMethod(targetClass, methodName); + // if (mJniSetter != 0) { + // if (propertyMap == null) { + // propertyMap = new HashMap(); + // sJNISetterPropertyMap.put(targetClass, propertyMap); + // } + // propertyMap.put(mPropertyName, mJniSetter); + // } + // } + //} catch (NoSuchMethodError e) { + // Log.d("PropertyValuesHolder", + // "Can't find native method using JNI, use reflection" + e); + //} finally { + // mPropertyMapLock.writeLock().unlock(); + //} + //if (mJniSetter == 0) { + // Couldn't find method through fast JNI approach - just use reflection + super.setupSetter(targetClass); + //} + } + } + + static class FloatPropertyValuesHolder extends PropertyValuesHolder { + + // Cache JNI functions to avoid looking them up twice + //private static final HashMap> sJNISetterPropertyMap = + // new HashMap>(); + //int mJniSetter; + //private FloatProperty mFloatProperty; + + FloatKeyframeSet mFloatKeyframeSet; + float mFloatAnimatedValue; + + public FloatPropertyValuesHolder(String propertyName, FloatKeyframeSet keyframeSet) { + super(propertyName); + mValueType = float.class; + mKeyframeSet = keyframeSet; + mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + } + + //public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) { + // super(property); + // mValueType = float.class; + // mKeyframeSet = keyframeSet; + // mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + // if (property instanceof FloatProperty) { + // mFloatProperty = (FloatProperty) mProperty; + // } + //} + + public FloatPropertyValuesHolder(String propertyName, float... values) { + super(propertyName); + setFloatValues(values); + } + + //public FloatPropertyValuesHolder(Property property, float... values) { + // super(property); + // setFloatValues(values); + // if (property instanceof FloatProperty) { + // mFloatProperty = (FloatProperty) mProperty; + // } + //} + + @Override + public void setFloatValues(float... values) { + super.setFloatValues(values); + mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + } + + @Override + void calculateValue(float fraction) { + mFloatAnimatedValue = mFloatKeyframeSet.getFloatValue(fraction); + } + + @Override + Object getAnimatedValue() { + return mFloatAnimatedValue; + } + + @Override + public FloatPropertyValuesHolder clone() { + FloatPropertyValuesHolder newPVH = (FloatPropertyValuesHolder) super.clone(); + newPVH.mFloatKeyframeSet = (FloatKeyframeSet) newPVH.mKeyframeSet; + return newPVH; + } + + /** + * Internal function to set the value on the target object, using the setter set up + * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator + * to handle turning the value calculated by ValueAnimator into a value set on the object + * according to the name of the property. + * @param target The target object on which the value is set + */ + @Override + void setAnimatedValue(Object target) { + //if (mFloatProperty != null) { + // mFloatProperty.setValue(target, mFloatAnimatedValue); + // return; + //} + //if (mProperty != null) { + // mProperty.set(target, mFloatAnimatedValue); + // return; + //} + //if (mJniSetter != 0) { + // nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue); + // return; + //} + if (mSetter != null) { + try { + mTmpValueArray[0] = mFloatAnimatedValue; + mSetter.invoke(target, mTmpValueArray); + } catch (InvocationTargetException e) { + Log.e("PropertyValuesHolder", e.toString()); + } catch (IllegalAccessException e) { + Log.e("PropertyValuesHolder", e.toString()); + } + } + } + + @Override + void setupSetter(Class targetClass) { + //if (mProperty != null) { + // return; + //} + // Check new static hashmap for setter method + //try { + // mPropertyMapLock.writeLock().lock(); + // HashMap propertyMap = sJNISetterPropertyMap.get(targetClass); + // if (propertyMap != null) { + // Integer mJniSetterInteger = propertyMap.get(mPropertyName); + // if (mJniSetterInteger != null) { + // mJniSetter = mJniSetterInteger; + // } + // } + // if (mJniSetter == 0) { + // String methodName = getMethodName("set", mPropertyName); + // mJniSetter = nGetFloatMethod(targetClass, methodName); + // if (mJniSetter != 0) { + // if (propertyMap == null) { + // propertyMap = new HashMap(); + // sJNISetterPropertyMap.put(targetClass, propertyMap); + // } + // propertyMap.put(mPropertyName, mJniSetter); + // } + // } + //} catch (NoSuchMethodError e) { + // Log.d("PropertyValuesHolder", + // "Can't find native method using JNI, use reflection" + e); + //} finally { + // mPropertyMapLock.writeLock().unlock(); + //} + //if (mJniSetter == 0) { + // Couldn't find method through fast JNI approach - just use reflection + super.setupSetter(targetClass); + //} + } + + } + + //native static private int nGetIntMethod(Class targetClass, String methodName); + //native static private int nGetFloatMethod(Class targetClass, String methodName); + //native static private void nCallIntMethod(Object target, int methodID, int arg); + //native static private void nCallFloatMethod(Object target, int methodID, float arg); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java new file mode 100644 index 000000000..0ea319244 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +/** + * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators + * allow developers to create animations on arbitrary property types, by allowing them to supply + * custom evaulators for types that are not automatically understood and used by the animation + * system. + * + * @see ValueAnimator#setEvaluator(TypeEvaluator) + */ +public interface TypeEvaluator { + + /** + * This function returns the result of linearly interpolating the start and end values, with + * fraction representing the proportion between the start and end values. The + * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), + * where x0 is startValue, x1 is endValue, + * and t is fraction. + * + * @param fraction The fraction from the starting to the ending values + * @param startValue The start value. + * @param endValue The end value. + * @return A linear interpolation between the start and end values, given the + * fraction parameter. + */ + public T evaluate(float fraction, T startValue, T endValue); + +} \ No newline at end of file diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java new file mode 100644 index 000000000..d8a12c688 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java @@ -0,0 +1,1265 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.nineoldandroids.animation; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.AndroidRuntimeException; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * This class provides a simple timing engine for running animations + * which calculate animated values and set them on target objects. + * + *

There is a single timing pulse that all animations use. It runs in a + * custom handler to ensure that property changes happen on the UI thread.

+ * + *

By default, ValueAnimator uses non-linear time interpolation, via the + * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates + * out of an animation. This behavior can be changed by calling + * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.

+ */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public class ValueAnimator extends Animator { + + /** + * Internal constants + */ + + /* + * The default amount of time in ms between animation frames + */ + private static final long DEFAULT_FRAME_DELAY = 10; + + /** + * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent + * by the handler to itself to process the next animation frame + */ + static final int ANIMATION_START = 0; + static final int ANIMATION_FRAME = 1; + + /** + * Values used with internal variable mPlayingState to indicate the current state of an + * animation. + */ + static final int STOPPED = 0; // Not yet playing + static final int RUNNING = 1; // Playing normally + static final int SEEKED = 2; // Seeked to some time value + + /** + * Internal variables + * NOTE: This object implements the clone() method, making a deep copy of any referenced + * objects. As other non-trivial fields are added to this class, make sure to add logic + * to clone() to make deep copies of them. + */ + + // The first time that the animation's animateFrame() method is called. This time is used to + // determine elapsed time (and therefore the elapsed fraction) in subsequent calls + // to animateFrame() + long mStartTime; + + /** + * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked + * to a value. + */ + long mSeekTime = -1; + + // TODO: We access the following ThreadLocal variables often, some of them on every update. + // If ThreadLocal access is significantly expensive, we may want to put all of these + // fields into a structure sot hat we just access ThreadLocal once to get the reference + // to that structure, then access the structure directly for each field. + + // The static sAnimationHandler processes the internal timing loop on which all animations + // are based + private static ThreadLocal sAnimationHandler = + new ThreadLocal(); + + // The per-thread list of all active animations + private static final ThreadLocal> sAnimations = + new ThreadLocal>() { + @Override + protected ArrayList initialValue() { + return new ArrayList(); + } + }; + + // The per-thread set of animations to be started on the next animation frame + private static final ThreadLocal> sPendingAnimations = + new ThreadLocal>() { + @Override + protected ArrayList initialValue() { + return new ArrayList(); + } + }; + + /** + * Internal per-thread collections used to avoid set collisions as animations start and end + * while being processed. + */ + private static final ThreadLocal> sDelayedAnims = + new ThreadLocal>() { + @Override + protected ArrayList initialValue() { + return new ArrayList(); + } + }; + + private static final ThreadLocal> sEndingAnims = + new ThreadLocal>() { + @Override + protected ArrayList initialValue() { + return new ArrayList(); + } + }; + + private static final ThreadLocal> sReadyAnims = + new ThreadLocal>() { + @Override + protected ArrayList initialValue() { + return new ArrayList(); + } + }; + + // The time interpolator to be used if none is set on the animation + private static final /*Time*/Interpolator sDefaultInterpolator = + new AccelerateDecelerateInterpolator(); + + // type evaluators for the primitive types handled by this implementation + //private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); + //private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); + + /** + * Used to indicate whether the animation is currently playing in reverse. This causes the + * elapsed fraction to be inverted to calculate the appropriate values. + */ + private boolean mPlayingBackwards = false; + + /** + * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the + * repeatCount (if repeatCount!=INFINITE), the animation ends + */ + private int mCurrentIteration = 0; + + /** + * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction(). + */ + private float mCurrentFraction = 0f; + + /** + * Tracks whether a startDelay'd animation has begun playing through the startDelay. + */ + private boolean mStartedDelay = false; + + /** + * Tracks the time at which the animation began playing through its startDelay. This is + * different from the mStartTime variable, which is used to track when the animation became + * active (which is when the startDelay expired and the animation was added to the active + * animations list). + */ + private long mDelayStartTime; + + /** + * Flag that represents the current state of the animation. Used to figure out when to start + * an animation (if state == STOPPED). Also used to end an animation that + * has been cancel()'d or end()'d since the last animation frame. Possible values are + * STOPPED, RUNNING, SEEKED. + */ + int mPlayingState = STOPPED; + + /** + * Additional playing state to indicate whether an animator has been start()'d. There is + * some lag between a call to start() and the first animation frame. We should still note + * that the animation has been started, even if it's first animation frame has not yet + * happened, and reflect that state in isRunning(). + * Note that delayed animations are different: they are not started until their first + * animation frame, which occurs after their delay elapses. + */ + private boolean mRunning = false; + + /** + * Additional playing state to indicate whether an animator has been start()'d, whether or + * not there is a nonzero startDelay. + */ + private boolean mStarted = false; + + /** + * Flag that denotes whether the animation is set up and ready to go. Used to + * set up animation that has not yet been started. + */ + boolean mInitialized = false; + + // + // Backing variables + // + + // How long the animation should last in ms + private long mDuration = 300; + + // The amount of time in ms to delay starting the animation after start() is called + private long mStartDelay = 0; + + // The number of milliseconds between animation frames + private static long sFrameDelay = DEFAULT_FRAME_DELAY; + + // The number of times the animation will repeat. The default is 0, which means the animation + // will play only once + private int mRepeatCount = 0; + + /** + * The type of repetition that will occur when repeatMode is nonzero. RESTART means the + * animation will start from the beginning on every new cycle. REVERSE means the animation + * will reverse directions on each iteration. + */ + private int mRepeatMode = RESTART; + + /** + * The time interpolator to be used. The elapsed fraction of the animation will be passed + * through this interpolator to calculate the interpolated fraction, which is then used to + * calculate the animated values. + */ + private /*Time*/Interpolator mInterpolator = sDefaultInterpolator; + + /** + * The set of listeners to be sent events through the life of an animation. + */ + private ArrayList mUpdateListeners = null; + + /** + * The property/value sets being animated. + */ + PropertyValuesHolder[] mValues; + + /** + * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values + * by property name during calls to getAnimatedValue(String). + */ + HashMap mValuesMap; + + /** + * Public constants + */ + + /** + * When the animation reaches the end and repeatCount is INFINITE + * or a positive value, the animation restarts from the beginning. + */ + public static final int RESTART = 1; + /** + * When the animation reaches the end and repeatCount is INFINITE + * or a positive value, the animation reverses direction on every iteration. + */ + public static final int REVERSE = 2; + /** + * This value used used with the {@link #setRepeatCount(int)} property to repeat + * the animation indefinitely. + */ + public static final int INFINITE = -1; + + /** + * Creates a new ValueAnimator object. This default constructor is primarily for + * use internally; the factory methods which take parameters are more generally + * useful. + */ + public ValueAnimator() { + } + + /** + * Constructs and returns a ValueAnimator that animates between int values. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + * @param values A set of values that the animation will animate between over time. + * @return A ValueAnimator object that is set up to animate between the given values. + */ + public static ValueAnimator ofInt(int... values) { + ValueAnimator anim = new ValueAnimator(); + anim.setIntValues(values); + return anim; + } + + /** + * Constructs and returns a ValueAnimator that animates between float values. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + * @param values A set of values that the animation will animate between over time. + * @return A ValueAnimator object that is set up to animate between the given values. + */ + public static ValueAnimator ofFloat(float... values) { + ValueAnimator anim = new ValueAnimator(); + anim.setFloatValues(values); + return anim; + } + + /** + * Constructs and returns a ValueAnimator that animates between the values + * specified in the PropertyValuesHolder objects. + * + * @param values A set of PropertyValuesHolder objects whose values will be animated + * between over time. + * @return A ValueAnimator object that is set up to animate between the given values. + */ + public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) { + ValueAnimator anim = new ValueAnimator(); + anim.setValues(values); + return anim; + } + /** + * Constructs and returns a ValueAnimator that animates between Object values. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + *

Since ValueAnimator does not know how to animate between arbitrary Objects, this + * factory method also takes a TypeEvaluator object that the ValueAnimator will use + * to perform that interpolation. + * + * @param evaluator A TypeEvaluator that will be called on each animation frame to + * provide the ncessry interpolation between the Object values to derive the animated + * value. + * @param values A set of values that the animation will animate between over time. + * @return A ValueAnimator object that is set up to animate between the given values. + */ + public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) { + ValueAnimator anim = new ValueAnimator(); + anim.setObjectValues(values); + anim.setEvaluator(evaluator); + return anim; + } + + /** + * Sets int values that will be animated between. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + *

If there are already multiple sets of values defined for this ValueAnimator via more + * than one PropertyValuesHolder object, this method will set the values for the first + * of those objects.

+ * + * @param values A set of values that the animation will animate between over time. + */ + public void setIntValues(int... values) { + if (values == null || values.length == 0) { + return; + } + if (mValues == null || mValues.length == 0) { + setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)}); + } else { + PropertyValuesHolder valuesHolder = mValues[0]; + valuesHolder.setIntValues(values); + } + // New property/values/target should cause re-initialization prior to starting + mInitialized = false; + } + + /** + * Sets float values that will be animated between. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + *

If there are already multiple sets of values defined for this ValueAnimator via more + * than one PropertyValuesHolder object, this method will set the values for the first + * of those objects.

+ * + * @param values A set of values that the animation will animate between over time. + */ + public void setFloatValues(float... values) { + if (values == null || values.length == 0) { + return; + } + if (mValues == null || mValues.length == 0) { + setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofFloat("", values)}); + } else { + PropertyValuesHolder valuesHolder = mValues[0]; + valuesHolder.setFloatValues(values); + } + // New property/values/target should cause re-initialization prior to starting + mInitialized = false; + } + + /** + * Sets the values to animate between for this animation. A single + * value implies that that value is the one being animated to. However, this is not typically + * useful in a ValueAnimator object because there is no way for the object to determine the + * starting value for the animation (unlike ObjectAnimator, which can derive that value + * from the target object and property being animated). Therefore, there should typically + * be two or more values. + * + *

If there are already multiple sets of values defined for this ValueAnimator via more + * than one PropertyValuesHolder object, this method will set the values for the first + * of those objects.

+ * + *

There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate + * between these value objects. ValueAnimator only knows how to interpolate between the + * primitive types specified in the other setValues() methods.

+ * + * @param values The set of values to animate between. + */ + public void setObjectValues(Object... values) { + if (values == null || values.length == 0) { + return; + } + if (mValues == null || mValues.length == 0) { + setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofObject("", + (TypeEvaluator)null, values)}); + } else { + PropertyValuesHolder valuesHolder = mValues[0]; + valuesHolder.setObjectValues(values); + } + // New property/values/target should cause re-initialization prior to starting + mInitialized = false; + } + + /** + * Sets the values, per property, being animated between. This function is called internally + * by the constructors of ValueAnimator that take a list of values. But an ValueAnimator can + * be constructed without values and this method can be called to set the values manually + * instead. + * + * @param values The set of values, per property, being animated between. + */ + public void setValues(PropertyValuesHolder... values) { + int numValues = values.length; + mValues = values; + mValuesMap = new HashMap(numValues); + for (int i = 0; i < numValues; ++i) { + PropertyValuesHolder valuesHolder = values[i]; + mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); + } + // New property/values/target should cause re-initialization prior to starting + mInitialized = false; + } + + /** + * Returns the values that this ValueAnimator animates between. These values are stored in + * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list + * of value objects instead. + * + * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the + * values, per property, that define the animation. + */ + public PropertyValuesHolder[] getValues() { + return mValues; + } + + /** + * This function is called immediately before processing the first animation + * frame of an animation. If there is a nonzero startDelay, the + * function is called after that delay ends. + * It takes care of the final initialization steps for the + * animation. + * + *

Overrides of this method should call the superclass method to ensure + * that internal mechanisms for the animation are set up correctly.

+ */ + void initAnimation() { + if (!mInitialized) { + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].init(); + } + mInitialized = true; + } + } + + + /** + * Sets the length of the animation. The default duration is 300 milliseconds. + * + * @param duration The length of the animation, in milliseconds. This value cannot + * be negative. + * @return ValueAnimator The object called with setDuration(). This return + * value makes it easier to compose statements together that construct and then set the + * duration, as in ValueAnimator.ofInt(0, 10).setDuration(500).start(). + */ + public ValueAnimator setDuration(long duration) { + if (duration < 0) { + throw new IllegalArgumentException("Animators cannot have negative duration: " + + duration); + } + mDuration = duration; + return this; + } + + /** + * Gets the length of the animation. The default duration is 300 milliseconds. + * + * @return The length of the animation, in milliseconds. + */ + public long getDuration() { + return mDuration; + } + + /** + * Sets the position of the animation to the specified point in time. This time should + * be between 0 and the total duration of the animation, including any repetition. If + * the animation has not yet been started, then it will not advance forward after it is + * set to this time; it will simply set the time to this value and perform any appropriate + * actions based on that time. If the animation is already running, then setCurrentPlayTime() + * will set the current playing time to this value and continue playing from that point. + * + * @param playTime The time, in milliseconds, to which the animation is advanced or rewound. + */ + public void setCurrentPlayTime(long playTime) { + initAnimation(); + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + if (mPlayingState != RUNNING) { + mSeekTime = playTime; + mPlayingState = SEEKED; + } + mStartTime = currentTime - playTime; + animationFrame(currentTime); + } + + /** + * Gets the current position of the animation in time, which is equal to the current + * time minus the time that the animation started. An animation that is not yet started will + * return a value of zero. + * + * @return The current position in time of the animation. + */ + public long getCurrentPlayTime() { + if (!mInitialized || mPlayingState == STOPPED) { + return 0; + } + return AnimationUtils.currentAnimationTimeMillis() - mStartTime; + } + + /** + * This custom, static handler handles the timing pulse that is shared by + * all active animations. This approach ensures that the setting of animation + * values will happen on the UI thread and that all animations will share + * the same times for calculating their values, which makes synchronizing + * animations possible. + * + */ + private static class AnimationHandler extends Handler { + /** + * There are only two messages that we care about: ANIMATION_START and + * ANIMATION_FRAME. The START message is sent when an animation's start() + * method is called. It cannot start synchronously when start() is called + * because the call may be on the wrong thread, and it would also not be + * synchronized with other animations because it would not start on a common + * timing pulse. So each animation sends a START message to the handler, which + * causes the handler to place the animation on the active animations queue and + * start processing frames for that animation. + * The FRAME message is the one that is sent over and over while there are any + * active animations to process. + */ + @Override + public void handleMessage(Message msg) { + boolean callAgain = true; + ArrayList animations = sAnimations.get(); + ArrayList delayedAnims = sDelayedAnims.get(); + switch (msg.what) { + // TODO: should we avoid sending frame message when starting if we + // were already running? + case ANIMATION_START: + ArrayList pendingAnimations = sPendingAnimations.get(); + if (animations.size() > 0 || delayedAnims.size() > 0) { + callAgain = false; + } + // pendingAnims holds any animations that have requested to be started + // We're going to clear sPendingAnimations, but starting animation may + // cause more to be added to the pending list (for example, if one animation + // starting triggers another starting). So we loop until sPendingAnimations + // is empty. + while (pendingAnimations.size() > 0) { + ArrayList pendingCopy = + (ArrayList) pendingAnimations.clone(); + pendingAnimations.clear(); + int count = pendingCopy.size(); + for (int i = 0; i < count; ++i) { + ValueAnimator anim = pendingCopy.get(i); + // If the animation has a startDelay, place it on the delayed list + if (anim.mStartDelay == 0) { + anim.startAnimation(); + } else { + delayedAnims.add(anim); + } + } + } + // fall through to process first frame of new animations + case ANIMATION_FRAME: + // currentTime holds the common time for all animations processed + // during this frame + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + ArrayList readyAnims = sReadyAnims.get(); + ArrayList endingAnims = sEndingAnims.get(); + + // First, process animations currently sitting on the delayed queue, adding + // them to the active animations if they are ready + int numDelayedAnims = delayedAnims.size(); + for (int i = 0; i < numDelayedAnims; ++i) { + ValueAnimator anim = delayedAnims.get(i); + if (anim.delayedAnimationFrame(currentTime)) { + readyAnims.add(anim); + } + } + int numReadyAnims = readyAnims.size(); + if (numReadyAnims > 0) { + for (int i = 0; i < numReadyAnims; ++i) { + ValueAnimator anim = readyAnims.get(i); + anim.startAnimation(); + anim.mRunning = true; + delayedAnims.remove(anim); + } + readyAnims.clear(); + } + + // Now process all active animations. The return value from animationFrame() + // tells the handler whether it should now be ended + int numAnims = animations.size(); + int i = 0; + while (i < numAnims) { + ValueAnimator anim = animations.get(i); + if (anim.animationFrame(currentTime)) { + endingAnims.add(anim); + } + if (animations.size() == numAnims) { + ++i; + } else { + // An animation might be canceled or ended by client code + // during the animation frame. Check to see if this happened by + // seeing whether the current index is the same as it was before + // calling animationFrame(). Another approach would be to copy + // animations to a temporary list and process that list instead, + // but that entails garbage and processing overhead that would + // be nice to avoid. + --numAnims; + endingAnims.remove(anim); + } + } + if (endingAnims.size() > 0) { + for (i = 0; i < endingAnims.size(); ++i) { + endingAnims.get(i).endAnimation(); + } + endingAnims.clear(); + } + + // If there are still active or delayed animations, call the handler again + // after the frameDelay + if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) { + sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay - + (AnimationUtils.currentAnimationTimeMillis() - currentTime))); + } + break; + } + } + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + * + * @return the number of milliseconds to delay running the animation + */ + public long getStartDelay() { + return mStartDelay; + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + + * @param startDelay The amount of the delay, in milliseconds + */ + public void setStartDelay(long startDelay) { + this.mStartDelay = startDelay; + } + + /** + * The amount of time, in milliseconds, between each frame of the animation. This is a + * requested time that the animation will attempt to honor, but the actual delay between + * frames may be different, depending on system load and capabilities. This is a static + * function because the same delay will be applied to all animations, since they are all + * run off of a single timing loop. + * + * @return the requested time between frames, in milliseconds + */ + public static long getFrameDelay() { + return sFrameDelay; + } + + /** + * The amount of time, in milliseconds, between each frame of the animation. This is a + * requested time that the animation will attempt to honor, but the actual delay between + * frames may be different, depending on system load and capabilities. This is a static + * function because the same delay will be applied to all animations, since they are all + * run off of a single timing loop. + * + * @param frameDelay the requested time between frames, in milliseconds + */ + public static void setFrameDelay(long frameDelay) { + sFrameDelay = frameDelay; + } + + /** + * The most recent value calculated by this ValueAnimator when there is just one + * property being animated. This value is only sensible while the animation is running. The main + * purpose for this read-only property is to retrieve the value from the ValueAnimator + * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which + * is called during each animation frame, immediately after the value is calculated. + * + * @return animatedValue The value most recently calculated by this ValueAnimator for + * the single property being animated. If there are several properties being animated + * (specified by several PropertyValuesHolder objects in the constructor), this function + * returns the animated value for the first of those objects. + */ + public Object getAnimatedValue() { + if (mValues != null && mValues.length > 0) { + return mValues[0].getAnimatedValue(); + } + // Shouldn't get here; should always have values unless ValueAnimator was set up wrong + return null; + } + + /** + * The most recent value calculated by this ValueAnimator for propertyName. + * The main purpose for this read-only property is to retrieve the value from the + * ValueAnimator during a call to + * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which + * is called during each animation frame, immediately after the value is calculated. + * + * @return animatedValue The value most recently calculated for the named property + * by this ValueAnimator. + */ + public Object getAnimatedValue(String propertyName) { + PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName); + if (valuesHolder != null) { + return valuesHolder.getAnimatedValue(); + } else { + // At least avoid crashing if called with bogus propertyName + return null; + } + } + + /** + * Sets how many times the animation should be repeated. If the repeat + * count is 0, the animation is never repeated. If the repeat count is + * greater than 0 or {@link #INFINITE}, the repeat mode will be taken + * into account. The repeat count is 0 by default. + * + * @param value the number of times the animation should be repeated + */ + public void setRepeatCount(int value) { + mRepeatCount = value; + } + /** + * Defines how many times the animation should repeat. The default value + * is 0. + * + * @return the number of times the animation should repeat, or {@link #INFINITE} + */ + public int getRepeatCount() { + return mRepeatCount; + } + + /** + * Defines what this animation should do when it reaches the end. This + * setting is applied only when the repeat count is either greater than + * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. + * + * @param value {@link #RESTART} or {@link #REVERSE} + */ + public void setRepeatMode(int value) { + mRepeatMode = value; + } + + /** + * Defines what this animation should do when it reaches the end. + * + * @return either one of {@link #REVERSE} or {@link #RESTART} + */ + public int getRepeatMode() { + return mRepeatMode; + } + + /** + * Adds a listener to the set of listeners that are sent update events through the life of + * an animation. This method is called on all listeners for every frame of the animation, + * after the values for the animation have been calculated. + * + * @param listener the listener to be added to the current set of listeners for this animation. + */ + public void addUpdateListener(AnimatorUpdateListener listener) { + if (mUpdateListeners == null) { + mUpdateListeners = new ArrayList(); + } + mUpdateListeners.add(listener); + } + + /** + * Removes all listeners from the set listening to frame updates for this animation. + */ + public void removeAllUpdateListeners() { + if (mUpdateListeners == null) { + return; + } + mUpdateListeners.clear(); + mUpdateListeners = null; + } + + /** + * Removes a listener from the set listening to frame updates for this animation. + * + * @param listener the listener to be removed from the current set of update listeners + * for this animation. + */ + public void removeUpdateListener(AnimatorUpdateListener listener) { + if (mUpdateListeners == null) { + return; + } + mUpdateListeners.remove(listener); + if (mUpdateListeners.size() == 0) { + mUpdateListeners = null; + } + } + + + /** + * The time interpolator used in calculating the elapsed fraction of this animation. The + * interpolator determines whether the animation runs with linear or non-linear motion, + * such as acceleration and deceleration. The default value is + * {@link android.view.animation.AccelerateDecelerateInterpolator} + * + * @param value the interpolator to be used by this animation. A value of null + * will result in linear interpolation. + */ + @Override + public void setInterpolator(/*Time*/Interpolator value) { + if (value != null) { + mInterpolator = value; + } else { + mInterpolator = new LinearInterpolator(); + } + } + + /** + * Returns the timing interpolator that this ValueAnimator uses. + * + * @return The timing interpolator for this ValueAnimator. + */ + public /*Time*/Interpolator getInterpolator() { + return mInterpolator; + } + + /** + * The type evaluator to be used when calculating the animated values of this animation. + * The system will automatically assign a float or int evaluator based on the type + * of startValue and endValue in the constructor. But if these values + * are not one of these primitive types, or if different evaluation is desired (such as is + * necessary with int values that represent colors), a custom evaluator needs to be assigned. + * For example, when running an animation on color values, the {@link ArgbEvaluator} + * should be used to get correct RGB color interpolation. + * + *

If this ValueAnimator has only one set of values being animated between, this evaluator + * will be used for that set. If there are several sets of values being animated, which is + * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator + * is assigned just to the first PropertyValuesHolder object.

+ * + * @param value the evaluator to be used this animation + */ + public void setEvaluator(TypeEvaluator value) { + if (value != null && mValues != null && mValues.length > 0) { + mValues[0].setEvaluator(value); + } + } + + /** + * Start the animation playing. This version of start() takes a boolean flag that indicates + * whether the animation should play in reverse. The flag is usually false, but may be set + * to true if called from the reverse() method. + * + *

The animation started by calling this method will be run on the thread that called + * this method. This thread should have a Looper on it (a runtime exception will be thrown if + * this is not the case). Also, if the animation will animate + * properties of objects in the view hierarchy, then the calling thread should be the UI + * thread for that view hierarchy.

+ * + * @param playBackwards Whether the ValueAnimator should start playing in reverse. + */ + private void start(boolean playBackwards) { + if (Looper.myLooper() == null) { + throw new AndroidRuntimeException("Animators may only be run on Looper threads"); + } + mPlayingBackwards = playBackwards; + mCurrentIteration = 0; + mPlayingState = STOPPED; + mStarted = true; + mStartedDelay = false; + sPendingAnimations.get().add(this); + if (mStartDelay == 0) { + // This sets the initial value of the animation, prior to actually starting it running + setCurrentPlayTime(getCurrentPlayTime()); + mPlayingState = STOPPED; + mRunning = true; + + if (mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationStart(this); + } + } + } + AnimationHandler animationHandler = sAnimationHandler.get(); + if (animationHandler == null) { + animationHandler = new AnimationHandler(); + sAnimationHandler.set(animationHandler); + } + animationHandler.sendEmptyMessage(ANIMATION_START); + } + + @Override + public void start() { + start(false); + } + + @Override + public void cancel() { + // Only cancel if the animation is actually running or has been started and is about + // to run + if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) || + sDelayedAnims.get().contains(this)) { + // Only notify listeners if the animator has actually started + if (mRunning && mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationCancel(this); + } + } + endAnimation(); + } + } + + @Override + public void end() { + if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) { + // Special case if the animation has not yet started; get it ready for ending + mStartedDelay = false; + startAnimation(); + } else if (!mInitialized) { + initAnimation(); + } + // The final value set on the target varies, depending on whether the animation + // was supposed to repeat an odd number of times + if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) { + animateValue(0f); + } else { + animateValue(1f); + } + endAnimation(); + } + + @Override + public boolean isRunning() { + return (mPlayingState == RUNNING || mRunning); + } + + @Override + public boolean isStarted() { + return mStarted; + } + + /** + * Plays the ValueAnimator in reverse. If the animation is already running, + * it will stop itself and play backwards from the point reached when reverse was called. + * If the animation is not currently running, then it will start from the end and + * play backwards. This behavior is only set for the current animation; future playing + * of the animation will use the default behavior of playing forward. + */ + public void reverse() { + mPlayingBackwards = !mPlayingBackwards; + if (mPlayingState == RUNNING) { + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + long currentPlayTime = currentTime - mStartTime; + long timeLeft = mDuration - currentPlayTime; + mStartTime = currentTime - timeLeft; + } else { + start(true); + } + } + + /** + * Called internally to end an animation by removing it from the animations list. Must be + * called on the UI thread. + */ + private void endAnimation() { + sAnimations.get().remove(this); + sPendingAnimations.get().remove(this); + sDelayedAnims.get().remove(this); + mPlayingState = STOPPED; + if (mRunning && mListeners != null) { + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationEnd(this); + } + } + mRunning = false; + mStarted = false; + } + + /** + * Called internally to start an animation by adding it to the active animations list. Must be + * called on the UI thread. + */ + private void startAnimation() { + initAnimation(); + sAnimations.get().add(this); + if (mStartDelay > 0 && mListeners != null) { + // Listeners were already notified in start() if startDelay is 0; this is + // just for delayed animations + ArrayList tmpListeners = + (ArrayList) mListeners.clone(); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationStart(this); + } + } + } + + /** + * Internal function called to process an animation frame on an animation that is currently + * sleeping through its startDelay phase. The return value indicates whether it + * should be woken up and put on the active animations queue. + * + * @param currentTime The current animation time, used to calculate whether the animation + * has exceeded its startDelay and should be started. + * @return True if the animation's startDelay has been exceeded and the animation + * should be added to the set of active animations. + */ + private boolean delayedAnimationFrame(long currentTime) { + if (!mStartedDelay) { + mStartedDelay = true; + mDelayStartTime = currentTime; + } else { + long deltaTime = currentTime - mDelayStartTime; + if (deltaTime > mStartDelay) { + // startDelay ended - start the anim and record the + // mStartTime appropriately + mStartTime = currentTime - (deltaTime - mStartDelay); + mPlayingState = RUNNING; + return true; + } + } + return false; + } + + /** + * This internal function processes a single animation frame for a given animation. The + * currentTime parameter is the timing pulse sent by the handler, used to calculate the + * elapsed duration, and therefore + * the elapsed fraction, of the animation. The return value indicates whether the animation + * should be ended (which happens when the elapsed time of the animation exceeds the + * animation's duration, including the repeatCount). + * + * @param currentTime The current time, as tracked by the static timing handler + * @return true if the animation's duration, including any repetitions due to + * repeatCount has been exceeded and the animation should be ended. + */ + boolean animationFrame(long currentTime) { + boolean done = false; + + if (mPlayingState == STOPPED) { + mPlayingState = RUNNING; + if (mSeekTime < 0) { + mStartTime = currentTime; + } else { + mStartTime = currentTime - mSeekTime; + // Now that we're playing, reset the seek time + mSeekTime = -1; + } + } + switch (mPlayingState) { + case RUNNING: + case SEEKED: + float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f; + if (fraction >= 1f) { + if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { + // Time to repeat + if (mListeners != null) { + int numListeners = mListeners.size(); + for (int i = 0; i < numListeners; ++i) { + mListeners.get(i).onAnimationRepeat(this); + } + } + if (mRepeatMode == REVERSE) { + mPlayingBackwards = mPlayingBackwards ? false : true; + } + mCurrentIteration += (int)fraction; + fraction = fraction % 1f; + mStartTime += mDuration; + } else { + done = true; + fraction = Math.min(fraction, 1.0f); + } + } + if (mPlayingBackwards) { + fraction = 1f - fraction; + } + animateValue(fraction); + break; + } + + return done; + } + + /** + * Returns the current animation fraction, which is the elapsed/interpolated fraction used in + * the most recent frame update on the animation. + * + * @return Elapsed/interpolated fraction of the animation. + */ + public float getAnimatedFraction() { + return mCurrentFraction; + } + + /** + * This method is called with the elapsed fraction of the animation during every + * animation frame. This function turns the elapsed fraction into an interpolated fraction + * and then into an animated value (from the evaluator. The function is called mostly during + * animation updates, but it is also called when the end() + * function is called, to set the final value on the property. + * + *

Overrides of this method must call the superclass to perform the calculation + * of the animated value.

+ * + * @param fraction The elapsed fraction of the animation. + */ + void animateValue(float fraction) { + fraction = mInterpolator.getInterpolation(fraction); + mCurrentFraction = fraction; + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].calculateValue(fraction); + } + if (mUpdateListeners != null) { + int numListeners = mUpdateListeners.size(); + for (int i = 0; i < numListeners; ++i) { + mUpdateListeners.get(i).onAnimationUpdate(this); + } + } + } + + @Override + public ValueAnimator clone() { + final ValueAnimator anim = (ValueAnimator) super.clone(); + if (mUpdateListeners != null) { + ArrayList oldListeners = mUpdateListeners; + anim.mUpdateListeners = new ArrayList(); + int numListeners = oldListeners.size(); + for (int i = 0; i < numListeners; ++i) { + anim.mUpdateListeners.add(oldListeners.get(i)); + } + } + anim.mSeekTime = -1; + anim.mPlayingBackwards = false; + anim.mCurrentIteration = 0; + anim.mInitialized = false; + anim.mPlayingState = STOPPED; + anim.mStartedDelay = false; + PropertyValuesHolder[] oldValues = mValues; + if (oldValues != null) { + int numValues = oldValues.length; + anim.mValues = new PropertyValuesHolder[numValues]; + anim.mValuesMap = new HashMap(numValues); + for (int i = 0; i < numValues; ++i) { + PropertyValuesHolder newValuesHolder = oldValues[i].clone(); + anim.mValues[i] = newValuesHolder; + anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder); + } + } + return anim; + } + + /** + * Implementors of this interface can add themselves as update listeners + * to an ValueAnimator instance to receive callbacks on every animation + * frame, after the current frame's values have been calculated for that + * ValueAnimator. + */ + public static interface AnimatorUpdateListener { + /** + *

Notifies the occurrence of another frame of the animation.

+ * + * @param animation The animation which was repeated. + */ + void onAnimationUpdate(ValueAnimator animation); + + } + + /** + * Return the number of animations currently running. + * + * Used by StrictMode internally to annotate violations. Only + * called on the main thread. + * + * @hide + */ + public static int getCurrentAnimationsCount() { + return sAnimations.get().size(); + } + + /** + * Clear all animations on this thread, without canceling or ending them. + * This should be used with caution. + * + * @hide + */ + public static void clearAllAnimations() { + sAnimations.get().clear(); + sPendingAnimations.get().clear(); + sDelayedAnims.get().clear(); + } + + @Override + public String toString() { + String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode()); + if (mValues != null) { + for (int i = 0; i < mValues.length; ++i) { + returnVal += "\n " + mValues[i].toString(); + } + } + return returnVal; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java new file mode 100644 index 000000000..7b830b9c0 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/NineViewGroup.java @@ -0,0 +1,79 @@ +package com.actionbarsherlock.internal.nineoldandroids.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.ViewGroup; + +import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; + +public abstract class NineViewGroup extends ViewGroup { + private final AnimatorProxy mProxy; + + public NineViewGroup(Context context) { + super(context); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + public NineViewGroup(Context context, AttributeSet attrs) { + super(context, attrs); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + public NineViewGroup(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + + @Override + public void setVisibility(int visibility) { + if (mProxy != null) { + if (visibility == GONE) { + clearAnimation(); + } else if (visibility == VISIBLE) { + setAnimation(mProxy); + } + } + super.setVisibility(visibility); + } + + public float getAlpha() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getAlpha(); + } else { + return super.getAlpha(); + } + } + public void setAlpha(float alpha) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setAlpha(alpha); + } else { + super.setAlpha(alpha); + } + } + public float getTranslationX() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getTranslationX(); + } else { + return super.getTranslationX(); + } + } + public void setTranslationX(float translationX) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setTranslationX(translationX); + } else { + super.setTranslationX(translationX); + } + } + public float getTranslationY() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getTranslationY(); + } else { + return super.getTranslationY(); + } + } + public void setTranslationY(float translationY) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setTranslationY(translationY); + } else { + super.setTranslationY(translationY); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java new file mode 100644 index 000000000..067d0494e --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/view/animation/AnimatorProxy.java @@ -0,0 +1,212 @@ +package com.actionbarsherlock.internal.nineoldandroids.view.animation; + +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; +import android.graphics.Matrix; +import android.graphics.RectF; +import android.os.Build; +import android.util.FloatMath; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.Transformation; + +public final class AnimatorProxy extends Animation { + public static final boolean NEEDS_PROXY = Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB; + + private static final WeakHashMap PROXIES = + new WeakHashMap(); + + public static AnimatorProxy wrap(View view) { + AnimatorProxy proxy = PROXIES.get(view); + if (proxy == null) { + proxy = new AnimatorProxy(view); + PROXIES.put(view, proxy); + } + return proxy; + } + + private final WeakReference mView; + + private float mAlpha = 1; + private float mScaleX = 1; + private float mScaleY = 1; + private float mTranslationX; + private float mTranslationY; + + private final RectF mBefore = new RectF(); + private final RectF mAfter = new RectF(); + private final Matrix mTempMatrix = new Matrix(); + + private AnimatorProxy(View view) { + setDuration(0); //perform transformation immediately + setFillAfter(true); //persist transformation beyond duration + view.setAnimation(this); + mView = new WeakReference(view); + } + + public float getAlpha() { + return mAlpha; + } + public void setAlpha(float alpha) { + if (mAlpha != alpha) { + mAlpha = alpha; + View view = mView.get(); + if (view != null) { + view.invalidate(); + } + } + } + public float getScaleX() { + return mScaleX; + } + public void setScaleX(float scaleX) { + if (mScaleX != scaleX) { + prepareForUpdate(); + mScaleX = scaleX; + invalidateAfterUpdate(); + } + } + public float getScaleY() { + return mScaleY; + } + public void setScaleY(float scaleY) { + if (mScaleY != scaleY) { + prepareForUpdate(); + mScaleY = scaleY; + invalidateAfterUpdate(); + } + } + public int getScrollX() { + View view = mView.get(); + if (view == null) { + return 0; + } + return view.getScrollX(); + } + public void setScrollX(int value) { + View view = mView.get(); + if (view != null) { + view.scrollTo(value, view.getScrollY()); + } + } + public int getScrollY() { + View view = mView.get(); + if (view == null) { + return 0; + } + return view.getScrollY(); + } + public void setScrollY(int value) { + View view = mView.get(); + if (view != null) { + view.scrollTo(view.getScrollY(), value); + } + } + + public float getTranslationX() { + return mTranslationX; + } + public void setTranslationX(float translationX) { + if (mTranslationX != translationX) { + prepareForUpdate(); + mTranslationX = translationX; + invalidateAfterUpdate(); + } + } + public float getTranslationY() { + return mTranslationY; + } + public void setTranslationY(float translationY) { + if (mTranslationY != translationY) { + prepareForUpdate(); + mTranslationY = translationY; + invalidateAfterUpdate(); + } + } + + private void prepareForUpdate() { + View view = mView.get(); + if (view != null) { + computeRect(mBefore, view); + } + } + private void invalidateAfterUpdate() { + View view = mView.get(); + if (view == null) { + return; + } + View parent = (View)view.getParent(); + if (parent == null) { + return; + } + + view.setAnimation(this); + + final RectF after = mAfter; + computeRect(after, view); + after.union(mBefore); + + parent.invalidate( + (int) FloatMath.floor(after.left), + (int) FloatMath.floor(after.top), + (int) FloatMath.ceil(after.right), + (int) FloatMath.ceil(after.bottom)); + } + + private void computeRect(final RectF r, View view) { + // compute current rectangle according to matrix transformation + final float w = view.getWidth(); + final float h = view.getHeight(); + + // use a rectangle at 0,0 to make sure we don't run into issues with scaling + r.set(0, 0, w, h); + + final Matrix m = mTempMatrix; + m.reset(); + transformMatrix(m, view); + mTempMatrix.mapRect(r); + + r.offset(view.getLeft(), view.getTop()); + + // Straighten coords if rotations flipped them + if (r.right < r.left) { + final float f = r.right; + r.right = r.left; + r.left = f; + } + if (r.bottom < r.top) { + final float f = r.top; + r.top = r.bottom; + r.bottom = f; + } + } + + private void transformMatrix(Matrix m, View view) { + final float w = view.getWidth(); + final float h = view.getHeight(); + + final float sX = mScaleX; + final float sY = mScaleY; + if ((sX != 1.0f) || (sY != 1.0f)) { + final float deltaSX = ((sX * w) - w) / 2f; + final float deltaSY = ((sY * h) - h) / 2f; + m.postScale(sX, sY); + m.postTranslate(-deltaSX, -deltaSY); + } + m.postTranslate(mTranslationX, mTranslationY); + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + View view = mView.get(); + if (view != null) { + t.setAlpha(mAlpha); + transformMatrix(t.getMatrix(), view); + } + } + + @Override + public void reset() { + /* Do nothing. */ + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java new file mode 100644 index 000000000..953e3e844 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineFrameLayout.java @@ -0,0 +1,57 @@ +package com.actionbarsherlock.internal.nineoldandroids.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; + +public class NineFrameLayout extends FrameLayout { + private final AnimatorProxy mProxy; + + public NineFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + + @Override + public void setVisibility(int visibility) { + if (mProxy != null) { + if (visibility == GONE) { + clearAnimation(); + } else if (visibility == VISIBLE) { + setAnimation(mProxy); + } + } + super.setVisibility(visibility); + } + + public float getAlpha() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getAlpha(); + } else { + return super.getAlpha(); + } + } + public void setAlpha(float alpha) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setAlpha(alpha); + } else { + super.setAlpha(alpha); + } + } + public float getTranslationY() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getTranslationY(); + } else { + return super.getTranslationY(); + } + } + public void setTranslationY(float translationY) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setTranslationY(translationY); + } else { + super.setTranslationY(translationY); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java new file mode 100644 index 000000000..129b5aaaa --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineHorizontalScrollView.java @@ -0,0 +1,41 @@ +package com.actionbarsherlock.internal.nineoldandroids.widget; + +import android.content.Context; +import android.widget.HorizontalScrollView; +import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; + +public class NineHorizontalScrollView extends HorizontalScrollView { + private final AnimatorProxy mProxy; + + public NineHorizontalScrollView(Context context) { + super(context); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + + @Override + public void setVisibility(int visibility) { + if (mProxy != null) { + if (visibility == GONE) { + clearAnimation(); + } else if (visibility == VISIBLE) { + setAnimation(mProxy); + } + } + super.setVisibility(visibility); + } + + public float getAlpha() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getAlpha(); + } else { + return super.getAlpha(); + } + } + public void setAlpha(float alpha) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setAlpha(alpha); + } else { + super.setAlpha(alpha); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java new file mode 100644 index 000000000..1f381013a --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/nineoldandroids/widget/NineLinearLayout.java @@ -0,0 +1,57 @@ +package com.actionbarsherlock.internal.nineoldandroids.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; + +public class NineLinearLayout extends LinearLayout { + private final AnimatorProxy mProxy; + + public NineLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null; + } + + @Override + public void setVisibility(int visibility) { + if (mProxy != null) { + if (visibility == GONE) { + clearAnimation(); + } else if (visibility == VISIBLE) { + setAnimation(mProxy); + } + } + super.setVisibility(visibility); + } + + public float getAlpha() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getAlpha(); + } else { + return super.getAlpha(); + } + } + public void setAlpha(float alpha) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setAlpha(alpha); + } else { + super.setAlpha(alpha); + } + } + public float getTranslationX() { + if (AnimatorProxy.NEEDS_PROXY) { + return mProxy.getTranslationX(); + } else { + return super.getTranslationX(); + } + } + public void setTranslationX(float translationX) { + if (AnimatorProxy.NEEDS_PROXY) { + mProxy.setTranslationX(translationX); + } else { + super.setTranslationX(translationX); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java new file mode 100644 index 000000000..b136d50f0 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/ActionProviderWrapper.java @@ -0,0 +1,40 @@ +package com.actionbarsherlock.internal.view; + +import com.actionbarsherlock.internal.view.menu.SubMenuWrapper; +import com.actionbarsherlock.view.ActionProvider; +import android.view.View; + +public class ActionProviderWrapper extends android.view.ActionProvider { + private final ActionProvider mProvider; + + + public ActionProviderWrapper(ActionProvider provider) { + super(null/*TODO*/); //XXX this *should* be unused + mProvider = provider; + } + + + public ActionProvider unwrap() { + return mProvider; + } + + @Override + public View onCreateActionView() { + return mProvider.onCreateActionView(); + } + + @Override + public boolean hasSubMenu() { + return mProvider.hasSubMenu(); + } + + @Override + public boolean onPerformDefaultAction() { + return mProvider.onPerformDefaultAction(); + } + + @Override + public void onPrepareSubMenu(android.view.SubMenu subMenu) { + mProvider.onPrepareSubMenu(new SubMenuWrapper(subMenu)); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java new file mode 100644 index 000000000..0a87bd3f7 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/StandaloneActionMode.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.actionbarsherlock.internal.view; + +import android.content.Context; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; + +import java.lang.ref.WeakReference; + +import com.actionbarsherlock.internal.view.menu.MenuBuilder; +import com.actionbarsherlock.internal.view.menu.MenuPopupHelper; +import com.actionbarsherlock.internal.view.menu.SubMenuBuilder; +import com.actionbarsherlock.internal.widget.ActionBarContextView; +import com.actionbarsherlock.view.ActionMode; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuInflater; +import com.actionbarsherlock.view.MenuItem; + +public class StandaloneActionMode extends ActionMode implements MenuBuilder.Callback { + private Context mContext; + private ActionBarContextView mContextView; + private ActionMode.Callback mCallback; + private WeakReference mCustomView; + private boolean mFinished; + private boolean mFocusable; + + private MenuBuilder mMenu; + + public StandaloneActionMode(Context context, ActionBarContextView view, + ActionMode.Callback callback, boolean isFocusable) { + mContext = context; + mContextView = view; + mCallback = callback; + + mMenu = new MenuBuilder(context).setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + mMenu.setCallback(this); + mFocusable = isFocusable; + } + + @Override + public void setTitle(CharSequence title) { + mContextView.setTitle(title); + } + + @Override + public void setSubtitle(CharSequence subtitle) { + mContextView.setSubtitle(subtitle); + } + + @Override + public void setTitle(int resId) { + setTitle(mContext.getString(resId)); + } + + @Override + public void setSubtitle(int resId) { + setSubtitle(mContext.getString(resId)); + } + + @Override + public void setCustomView(View view) { + mContextView.setCustomView(view); + mCustomView = view != null ? new WeakReference(view) : null; + } + + @Override + public void invalidate() { + mCallback.onPrepareActionMode(this, mMenu); + } + + @Override + public void finish() { + if (mFinished) { + return; + } + mFinished = true; + + mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); + mCallback.onDestroyActionMode(this); + } + + @Override + public Menu getMenu() { + return mMenu; + } + + @Override + public CharSequence getTitle() { + return mContextView.getTitle(); + } + + @Override + public CharSequence getSubtitle() { + return mContextView.getSubtitle(); + } + + @Override + public View getCustomView() { + return mCustomView != null ? mCustomView.get() : null; + } + + @Override + public MenuInflater getMenuInflater() { + return new MenuInflater(mContext); + } + + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { + return mCallback.onActionItemClicked(this, item); + } + + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + } + + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + if (!subMenu.hasVisibleItems()) { + return true; + } + + new MenuPopupHelper(mContext, subMenu).show(); + return true; + } + + public void onCloseSubMenu(SubMenuBuilder menu) { + } + + public void onMenuModeChange(MenuBuilder menu) { + invalidate(); + mContextView.showOverflowMenu(); + } + + public boolean isUiFocusable() { + return mFocusable; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java new file mode 100644 index 000000000..7d45e81be --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_HasStateListenerSupport.java @@ -0,0 +1,6 @@ +package com.actionbarsherlock.internal.view; + +public interface View_HasStateListenerSupport { + void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener); + void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java new file mode 100644 index 000000000..3869d3290 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/View_OnAttachStateChangeListener.java @@ -0,0 +1,8 @@ +package com.actionbarsherlock.internal.view; + +import android.view.View; + +public interface View_OnAttachStateChangeListener { + void onViewAttachedToWindow(View v); + void onViewDetachedFromWindow(View v); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java new file mode 100644 index 000000000..0354ad1ad --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenu.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import java.util.ArrayList; +import java.util.List; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.view.KeyEvent; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +/** + * @hide + */ +public class ActionMenu implements Menu { + private Context mContext; + + private boolean mIsQwerty; + + private ArrayList mItems; + + public ActionMenu(Context context) { + mContext = context; + mItems = new ArrayList(); + } + + public Context getContext() { + return mContext; + } + + public MenuItem add(CharSequence title) { + return add(0, 0, 0, title); + } + + public MenuItem add(int titleRes) { + return add(0, 0, 0, titleRes); + } + + public MenuItem add(int groupId, int itemId, int order, int titleRes) { + return add(groupId, itemId, order, mContext.getResources().getString(titleRes)); + } + + public MenuItem add(int groupId, int itemId, int order, CharSequence title) { + ActionMenuItem item = new ActionMenuItem(getContext(), + groupId, itemId, 0, order, title); + mItems.add(order, item); + return item; + } + + public int addIntentOptions(int groupId, int itemId, int order, + ComponentName caller, Intent[] specifics, Intent intent, int flags, + MenuItem[] outSpecificItems) { + PackageManager pm = mContext.getPackageManager(); + final List lri = + pm.queryIntentActivityOptions(caller, specifics, intent, 0); + final int N = lri != null ? lri.size() : 0; + + if ((flags & FLAG_APPEND_TO_GROUP) == 0) { + removeGroup(groupId); + } + + for (int i=0; i= 0) { + outSpecificItems[ri.specificIndex] = item; + } + } + + return N; + } + + public SubMenu addSubMenu(CharSequence title) { + // TODO Implement submenus + return null; + } + + public SubMenu addSubMenu(int titleRes) { + // TODO Implement submenus + return null; + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, + CharSequence title) { + // TODO Implement submenus + return null; + } + + public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { + // TODO Implement submenus + return null; + } + + public void clear() { + mItems.clear(); + } + + public void close() { + } + + private int findItemIndex(int id) { + final ArrayList items = mItems; + final int itemCount = items.size(); + for (int i = 0; i < itemCount; i++) { + if (items.get(i).getItemId() == id) { + return i; + } + } + + return -1; + } + + public MenuItem findItem(int id) { + return mItems.get(findItemIndex(id)); + } + + public MenuItem getItem(int index) { + return mItems.get(index); + } + + public boolean hasVisibleItems() { + final ArrayList items = mItems; + final int itemCount = items.size(); + + for (int i = 0; i < itemCount; i++) { + if (items.get(i).isVisible()) { + return true; + } + } + + return false; + } + + private ActionMenuItem findItemWithShortcut(int keyCode, KeyEvent event) { + // TODO Make this smarter. + final boolean qwerty = mIsQwerty; + final ArrayList items = mItems; + final int itemCount = items.size(); + + for (int i = 0; i < itemCount; i++) { + ActionMenuItem item = items.get(i); + final char shortcut = qwerty ? item.getAlphabeticShortcut() : + item.getNumericShortcut(); + if (keyCode == shortcut) { + return item; + } + } + return null; + } + + public boolean isShortcutKey(int keyCode, KeyEvent event) { + return findItemWithShortcut(keyCode, event) != null; + } + + public boolean performIdentifierAction(int id, int flags) { + final int index = findItemIndex(id); + if (index < 0) { + return false; + } + + return mItems.get(index).invoke(); + } + + public boolean performShortcut(int keyCode, KeyEvent event, int flags) { + ActionMenuItem item = findItemWithShortcut(keyCode, event); + if (item == null) { + return false; + } + + return item.invoke(); + } + + public void removeGroup(int groupId) { + final ArrayList items = mItems; + int itemCount = items.size(); + int i = 0; + while (i < itemCount) { + if (items.get(i).getGroupId() == groupId) { + items.remove(i); + itemCount--; + } else { + i++; + } + } + } + + public void removeItem(int id) { + mItems.remove(findItemIndex(id)); + } + + public void setGroupCheckable(int group, boolean checkable, + boolean exclusive) { + final ArrayList items = mItems; + final int itemCount = items.size(); + + for (int i = 0; i < itemCount; i++) { + ActionMenuItem item = items.get(i); + if (item.getGroupId() == group) { + item.setCheckable(checkable); + item.setExclusiveCheckable(exclusive); + } + } + } + + public void setGroupEnabled(int group, boolean enabled) { + final ArrayList items = mItems; + final int itemCount = items.size(); + + for (int i = 0; i < itemCount; i++) { + ActionMenuItem item = items.get(i); + if (item.getGroupId() == group) { + item.setEnabled(enabled); + } + } + } + + public void setGroupVisible(int group, boolean visible) { + final ArrayList items = mItems; + final int itemCount = items.size(); + + for (int i = 0; i < itemCount; i++) { + ActionMenuItem item = items.get(i); + if (item.getGroupId() == group) { + item.setVisible(visible); + } + } + } + + public void setQwertyMode(boolean isQwerty) { + mIsQwerty = isQwerty; + } + + public int size() { + return mItems.size(); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java new file mode 100644 index 000000000..510b97488 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItem.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.View; + +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +/** + * @hide + */ +public class ActionMenuItem implements MenuItem { + private final int mId; + private final int mGroup; + //UNUSED private final int mCategoryOrder; + private final int mOrdering; + + private CharSequence mTitle; + private CharSequence mTitleCondensed; + private Intent mIntent; + private char mShortcutNumericChar; + private char mShortcutAlphabeticChar; + + private Drawable mIconDrawable; + //UNUSED private int mIconResId = NO_ICON; + + private Context mContext; + + private MenuItem.OnMenuItemClickListener mClickListener; + + //UNUSED private static final int NO_ICON = 0; + + private int mFlags = ENABLED; + private static final int CHECKABLE = 0x00000001; + private static final int CHECKED = 0x00000002; + private static final int EXCLUSIVE = 0x00000004; + private static final int HIDDEN = 0x00000008; + private static final int ENABLED = 0x00000010; + + public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering, + CharSequence title) { + mContext = context; + mId = id; + mGroup = group; + //UNUSED mCategoryOrder = categoryOrder; + mOrdering = ordering; + mTitle = title; + } + + public char getAlphabeticShortcut() { + return mShortcutAlphabeticChar; + } + + public int getGroupId() { + return mGroup; + } + + public Drawable getIcon() { + return mIconDrawable; + } + + public Intent getIntent() { + return mIntent; + } + + public int getItemId() { + return mId; + } + + public ContextMenuInfo getMenuInfo() { + return null; + } + + public char getNumericShortcut() { + return mShortcutNumericChar; + } + + public int getOrder() { + return mOrdering; + } + + public SubMenu getSubMenu() { + return null; + } + + public CharSequence getTitle() { + return mTitle; + } + + public CharSequence getTitleCondensed() { + return mTitleCondensed; + } + + public boolean hasSubMenu() { + return false; + } + + public boolean isCheckable() { + return (mFlags & CHECKABLE) != 0; + } + + public boolean isChecked() { + return (mFlags & CHECKED) != 0; + } + + public boolean isEnabled() { + return (mFlags & ENABLED) != 0; + } + + public boolean isVisible() { + return (mFlags & HIDDEN) == 0; + } + + public MenuItem setAlphabeticShortcut(char alphaChar) { + mShortcutAlphabeticChar = alphaChar; + return this; + } + + public MenuItem setCheckable(boolean checkable) { + mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0); + return this; + } + + public ActionMenuItem setExclusiveCheckable(boolean exclusive) { + mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0); + return this; + } + + public MenuItem setChecked(boolean checked) { + mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0); + return this; + } + + public MenuItem setEnabled(boolean enabled) { + mFlags = (mFlags & ~ENABLED) | (enabled ? ENABLED : 0); + return this; + } + + public MenuItem setIcon(Drawable icon) { + mIconDrawable = icon; + //UNUSED mIconResId = NO_ICON; + return this; + } + + public MenuItem setIcon(int iconRes) { + //UNUSED mIconResId = iconRes; + mIconDrawable = mContext.getResources().getDrawable(iconRes); + return this; + } + + public MenuItem setIntent(Intent intent) { + mIntent = intent; + return this; + } + + public MenuItem setNumericShortcut(char numericChar) { + mShortcutNumericChar = numericChar; + return this; + } + + public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) { + mClickListener = menuItemClickListener; + return this; + } + + public MenuItem setShortcut(char numericChar, char alphaChar) { + mShortcutNumericChar = numericChar; + mShortcutAlphabeticChar = alphaChar; + return this; + } + + public MenuItem setTitle(CharSequence title) { + mTitle = title; + return this; + } + + public MenuItem setTitle(int title) { + mTitle = mContext.getResources().getString(title); + return this; + } + + public MenuItem setTitleCondensed(CharSequence title) { + mTitleCondensed = title; + return this; + } + + public MenuItem setVisible(boolean visible) { + mFlags = (mFlags & HIDDEN) | (visible ? 0 : HIDDEN); + return this; + } + + public boolean invoke() { + if (mClickListener != null && mClickListener.onMenuItemClick(this)) { + return true; + } + + if (mIntent != null) { + mContext.startActivity(mIntent); + return true; + } + + return false; + } + + public void setShowAsAction(int show) { + // Do nothing. ActionMenuItems always show as action buttons. + } + + public MenuItem setActionView(View actionView) { + throw new UnsupportedOperationException(); + } + + public View getActionView() { + return null; + } + + @Override + public MenuItem setActionView(int resId) { + throw new UnsupportedOperationException(); + } + + @Override + public ActionProvider getActionProvider() { + return null; + } + + @Override + public MenuItem setActionProvider(ActionProvider actionProvider) { + throw new UnsupportedOperationException(); + } + + @Override + public MenuItem setShowAsActionFlags(int actionEnum) { + setShowAsAction(actionEnum); + return this; + } + + @Override + public boolean expandActionView() { + return false; + } + + @Override + public boolean collapseActionView() { + return false; + } + + @Override + public boolean isActionViewExpanded() { + return false; + } + + @Override + public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { + // No need to save the listener; ActionMenuItem does not support collapsing items. + return this; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java new file mode 100644 index 000000000..dcb50f362 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuItemView.java @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import java.util.HashSet; +import java.util.Set; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.Toast; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.view.View_HasStateListenerSupport; +import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener; +import com.actionbarsherlock.internal.widget.CapitalizingButton; + +import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; + +/** + * @hide + */ +public class ActionMenuItemView extends LinearLayout + implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener, + ActionMenuView.ActionMenuChildView, View_HasStateListenerSupport { + //UNUSED private static final String TAG = "ActionMenuItemView"; + + private MenuItemImpl mItemData; + private CharSequence mTitle; + private MenuBuilder.ItemInvoker mItemInvoker; + + private ImageButton mImageButton; + private CapitalizingButton mTextButton; + private boolean mAllowTextWithIcon; + private boolean mExpandedFormat; + private int mMinWidth; + + private final Set mListeners = new HashSet(); + + public ActionMenuItemView(Context context) { + this(context, null); + } + + public ActionMenuItemView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ActionMenuItemView(Context context, AttributeSet attrs, int defStyle) { + //TODO super(context, attrs, defStyle); + super(context, attrs); + mAllowTextWithIcon = getResources_getBoolean(context, + R.bool.abs__config_allowActionMenuItemTextWithIcon); + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.SherlockActionMenuItemView, 0, 0); + mMinWidth = a.getDimensionPixelSize( + R.styleable.SherlockActionMenuItemView_android_minWidth, 0); + a.recycle(); + } + + @Override + public void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { + mListeners.add(listener); + } + + @Override + public void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { + mListeners.remove(listener); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + for (View_OnAttachStateChangeListener listener : mListeners) { + listener.onViewAttachedToWindow(this); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (View_OnAttachStateChangeListener listener : mListeners) { + listener.onViewDetachedFromWindow(this); + } + } + + @Override + public void onFinishInflate() { + + mImageButton = (ImageButton) findViewById(R.id.abs__imageButton); + mTextButton = (CapitalizingButton) findViewById(R.id.abs__textButton); + mImageButton.setOnClickListener(this); + mTextButton.setOnClickListener(this); + mImageButton.setOnLongClickListener(this); + setOnClickListener(this); + setOnLongClickListener(this); + } + + public MenuItemImpl getItemData() { + return mItemData; + } + + public void initialize(MenuItemImpl itemData, int menuType) { + mItemData = itemData; + + setIcon(itemData.getIcon()); + setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon + setId(itemData.getItemId()); + + setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); + setEnabled(itemData.isEnabled()); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + mImageButton.setEnabled(enabled); + mTextButton.setEnabled(enabled); + } + + public void onClick(View v) { + if (mItemInvoker != null) { + mItemInvoker.invokeItem(mItemData); + } + } + + public void setItemInvoker(MenuBuilder.ItemInvoker invoker) { + mItemInvoker = invoker; + } + + public boolean prefersCondensedTitle() { + return true; + } + + public void setCheckable(boolean checkable) { + // TODO Support checkable action items + } + + public void setChecked(boolean checked) { + // TODO Support checkable action items + } + + public void setExpandedFormat(boolean expandedFormat) { + if (mExpandedFormat != expandedFormat) { + mExpandedFormat = expandedFormat; + if (mItemData != null) { + mItemData.actionFormatChanged(); + } + } + } + + private void updateTextButtonVisibility() { + boolean visible = !TextUtils.isEmpty(mTextButton.getText()); + visible &= mImageButton.getDrawable() == null || + (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat)); + + mTextButton.setVisibility(visible ? VISIBLE : GONE); + } + + public void setIcon(Drawable icon) { + mImageButton.setImageDrawable(icon); + if (icon != null) { + mImageButton.setVisibility(VISIBLE); + } else { + mImageButton.setVisibility(GONE); + } + + updateTextButtonVisibility(); + } + + public boolean hasText() { + return mTextButton.getVisibility() != GONE; + } + + public void setShortcut(boolean showShortcut, char shortcutKey) { + // Action buttons don't show text for shortcut keys. + } + + public void setTitle(CharSequence title) { + mTitle = title; + + mTextButton.setTextCompat(mTitle); + + setContentDescription(mTitle); + updateTextButtonVisibility(); + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + onPopulateAccessibilityEvent(event); + return true; + } + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + super.onPopulateAccessibilityEvent(event); + } + final CharSequence cdesc = getContentDescription(); + if (!TextUtils.isEmpty(cdesc)) { + event.getText().add(cdesc); + } + } + + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Don't allow children to hover; we want this to be treated as a single component. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return onHoverEvent(event); + } + return false; + } + + public boolean showsIcon() { + return true; + } + + public boolean needsDividerBefore() { + return hasText() && mItemData.getIcon() == null; + } + + public boolean needsDividerAfter() { + return hasText(); + } + + @Override + public boolean onLongClick(View v) { + if (hasText()) { + // Don't show the cheat sheet for items that already show text. + return false; + } + + final int[] screenPos = new int[2]; + final Rect displayFrame = new Rect(); + getLocationOnScreen(screenPos); + getWindowVisibleDisplayFrame(displayFrame); + + final Context context = getContext(); + final int width = getWidth(); + final int height = getHeight(); + final int midy = screenPos[1] + height / 2; + final int screenWidth = context.getResources().getDisplayMetrics().widthPixels; + + Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT); + if (midy < displayFrame.height()) { + // Show along the top; follow action buttons + cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT, + screenWidth - screenPos[0] - width / 2, height); + } else { + // Show along the bottom center + cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height); + } + cheatSheet.show(); + return true; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final int specSize = MeasureSpec.getSize(widthMeasureSpec); + final int oldMeasuredWidth = getMeasuredWidth(); + final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(specSize, mMinWidth) + : mMinWidth; + + if (widthMode != MeasureSpec.EXACTLY && mMinWidth > 0 && oldMeasuredWidth < targetWidth) { + // Remeasure at exactly the minimum width. + super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), + heightMeasureSpec); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java new file mode 100644 index 000000000..876a22c58 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java @@ -0,0 +1,714 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getInteger; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.SparseBooleanArray; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.widget.ImageButton; +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.view.View_HasStateListenerSupport; +import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener; +import com.actionbarsherlock.internal.view.menu.ActionMenuView.ActionMenuChildView; +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.MenuItem; + +/** + * MenuPresenter for building action menus as seen in the action bar and action modes. + */ +public class ActionMenuPresenter extends BaseMenuPresenter + implements ActionProvider.SubUiVisibilityListener { + //UNUSED private static final String TAG = "ActionMenuPresenter"; + + private View mOverflowButton; + private boolean mReserveOverflow; + private boolean mReserveOverflowSet; + private int mWidthLimit; + private int mActionItemWidthLimit; + private int mMaxItems; + private boolean mMaxItemsSet; + private boolean mStrictWidthLimit; + private boolean mWidthLimitSet; + private boolean mExpandedActionViewsExclusive; + + private int mMinCellSize; + + // Group IDs that have been added as actions - used temporarily, allocated here for reuse. + private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray(); + + private View mScrapActionButtonView; + + private OverflowPopup mOverflowPopup; + private ActionButtonSubmenu mActionButtonPopup; + + private OpenOverflowRunnable mPostedOpenRunnable; + + final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback(); + int mOpenSubMenuId; + + public ActionMenuPresenter(Context context) { + super(context, R.layout.abs__action_menu_layout, + R.layout.abs__action_menu_item_layout); + } + + @Override + public void initForMenu(Context context, MenuBuilder menu) { + super.initForMenu(context, menu); + + final Resources res = context.getResources(); + + if (!mReserveOverflowSet) { + mReserveOverflow = reserveOverflow(mContext); + } + + if (!mWidthLimitSet) { + mWidthLimit = res.getDisplayMetrics().widthPixels / 2; + } + + // Measure for initial configuration + if (!mMaxItemsSet) { + mMaxItems = getResources_getInteger(context, R.integer.abs__max_action_buttons); + } + + int width = mWidthLimit; + if (mReserveOverflow) { + if (mOverflowButton == null) { + mOverflowButton = new OverflowMenuButton(mSystemContext); + final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + mOverflowButton.measure(spec, spec); + } + width -= mOverflowButton.getMeasuredWidth(); + } else { + mOverflowButton = null; + } + + mActionItemWidthLimit = width; + + mMinCellSize = (int) (ActionMenuView.MIN_CELL_SIZE * res.getDisplayMetrics().density); + + // Drop a scrap view as it may no longer reflect the proper context/config. + mScrapActionButtonView = null; + } + + public static boolean reserveOverflow(Context context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB); + } else { + return !HasPermanentMenuKey.get(context); + } + } + + private static class HasPermanentMenuKey { + public static boolean get(Context context) { + return ViewConfiguration.get(context).hasPermanentMenuKey(); + } + } + + public void onConfigurationChanged(Configuration newConfig) { + if (!mMaxItemsSet) { + mMaxItems = getResources_getInteger(mContext, + R.integer.abs__max_action_buttons); + if (mMenu != null) { + mMenu.onItemsChanged(true); + } + } + } + + public void setWidthLimit(int width, boolean strict) { + mWidthLimit = width; + mStrictWidthLimit = strict; + mWidthLimitSet = true; + } + + public void setReserveOverflow(boolean reserveOverflow) { + mReserveOverflow = reserveOverflow; + mReserveOverflowSet = true; + } + + public void setItemLimit(int itemCount) { + mMaxItems = itemCount; + mMaxItemsSet = true; + } + + public void setExpandedActionViewsExclusive(boolean isExclusive) { + mExpandedActionViewsExclusive = isExclusive; + } + + @Override + public MenuView getMenuView(ViewGroup root) { + MenuView result = super.getMenuView(root); + ((ActionMenuView) result).setPresenter(this); + return result; + } + + @Override + public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) { + View actionView = item.getActionView(); + if (actionView == null || item.hasCollapsibleActionView()) { + if (!(convertView instanceof ActionMenuItemView)) { + convertView = null; + } + actionView = super.getItemView(item, convertView, parent); + } + actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE); + + final ActionMenuView menuParent = (ActionMenuView) parent; + final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); + if (!menuParent.checkLayoutParams(lp)) { + actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); + } + return actionView; + } + + @Override + public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) { + itemView.initialize(item, 0); + + final ActionMenuView menuView = (ActionMenuView) mMenuView; + ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; + actionItemView.setItemInvoker(menuView); + } + + @Override + public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) { + return item.isActionButton(); + } + + @Override + public void updateMenuView(boolean cleared) { + super.updateMenuView(cleared); + + if (mMenu != null) { + final ArrayList actionItems = mMenu.getActionItems(); + final int count = actionItems.size(); + for (int i = 0; i < count; i++) { + final ActionProvider provider = actionItems.get(i).getActionProvider(); + if (provider != null) { + provider.setSubUiVisibilityListener(this); + } + } + } + + final ArrayList nonActionItems = mMenu != null ? + mMenu.getNonActionItems() : null; + + boolean hasOverflow = false; + if (mReserveOverflow && nonActionItems != null) { + final int count = nonActionItems.size(); + if (count == 1) { + hasOverflow = !nonActionItems.get(0).isActionViewExpanded(); + } else { + hasOverflow = count > 0; + } + } + + if (hasOverflow) { + if (mOverflowButton == null) { + mOverflowButton = new OverflowMenuButton(mSystemContext); + } + ViewGroup parent = (ViewGroup) mOverflowButton.getParent(); + if (parent != mMenuView) { + if (parent != null) { + parent.removeView(mOverflowButton); + } + ActionMenuView menuView = (ActionMenuView) mMenuView; + menuView.addView(mOverflowButton, menuView.generateOverflowButtonLayoutParams()); + } + } else if (mOverflowButton != null && mOverflowButton.getParent() == mMenuView) { + ((ViewGroup) mMenuView).removeView(mOverflowButton); + } + + ((ActionMenuView) mMenuView).setOverflowReserved(mReserveOverflow); + } + + @Override + public boolean filterLeftoverView(ViewGroup parent, int childIndex) { + if (parent.getChildAt(childIndex) == mOverflowButton) return false; + return super.filterLeftoverView(parent, childIndex); + } + + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + if (!subMenu.hasVisibleItems()) return false; + + SubMenuBuilder topSubMenu = subMenu; + while (topSubMenu.getParentMenu() != mMenu) { + topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu(); + } + View anchor = findViewForItem(topSubMenu.getItem()); + if (anchor == null) { + if (mOverflowButton == null) return false; + anchor = mOverflowButton; + } + + mOpenSubMenuId = subMenu.getItem().getItemId(); + mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu); + mActionButtonPopup.setAnchorView(anchor); + mActionButtonPopup.show(); + super.onSubMenuSelected(subMenu); + return true; + } + + private View findViewForItem(MenuItem item) { + final ViewGroup parent = (ViewGroup) mMenuView; + if (parent == null) return null; + + final int count = parent.getChildCount(); + for (int i = 0; i < count; i++) { + final View child = parent.getChildAt(i); + if (child instanceof MenuView.ItemView && + ((MenuView.ItemView) child).getItemData() == item) { + return child; + } + } + return null; + } + + /** + * Display the overflow menu if one is present. + * @return true if the overflow menu was shown, false otherwise. + */ + public boolean showOverflowMenu() { + if (mReserveOverflow && !isOverflowMenuShowing() && mMenu != null && mMenuView != null && + mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) { + OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true); + mPostedOpenRunnable = new OpenOverflowRunnable(popup); + // Post this for later; we might still need a layout for the anchor to be right. + ((View) mMenuView).post(mPostedOpenRunnable); + + // ActionMenuPresenter uses null as a callback argument here + // to indicate overflow is opening. + super.onSubMenuSelected(null); + + return true; + } + return false; + } + + /** + * Hide the overflow menu if it is currently showing. + * + * @return true if the overflow menu was hidden, false otherwise. + */ + public boolean hideOverflowMenu() { + if (mPostedOpenRunnable != null && mMenuView != null) { + ((View) mMenuView).removeCallbacks(mPostedOpenRunnable); + mPostedOpenRunnable = null; + return true; + } + + MenuPopupHelper popup = mOverflowPopup; + if (popup != null) { + popup.dismiss(); + return true; + } + return false; + } + + /** + * Dismiss all popup menus - overflow and submenus. + * @return true if popups were dismissed, false otherwise. (This can be because none were open.) + */ + public boolean dismissPopupMenus() { + boolean result = hideOverflowMenu(); + result |= hideSubMenus(); + return result; + } + + /** + * Dismiss all submenu popups. + * + * @return true if popups were dismissed, false otherwise. (This can be because none were open.) + */ + public boolean hideSubMenus() { + if (mActionButtonPopup != null) { + mActionButtonPopup.dismiss(); + return true; + } + return false; + } + + /** + * @return true if the overflow menu is currently showing + */ + public boolean isOverflowMenuShowing() { + return mOverflowPopup != null && mOverflowPopup.isShowing(); + } + + /** + * @return true if space has been reserved in the action menu for an overflow item. + */ + public boolean isOverflowReserved() { + return mReserveOverflow; + } + + public boolean flagActionItems() { + final ArrayList visibleItems = mMenu.getVisibleItems(); + final int itemsSize = visibleItems.size(); + int maxActions = mMaxItems; + int widthLimit = mActionItemWidthLimit; + final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final ViewGroup parent = (ViewGroup) mMenuView; + + int requiredItems = 0; + int requestedItems = 0; + int firstActionWidth = 0; + boolean hasOverflow = false; + for (int i = 0; i < itemsSize; i++) { + MenuItemImpl item = visibleItems.get(i); + if (item.requiresActionButton()) { + requiredItems++; + } else if (item.requestsActionButton()) { + requestedItems++; + } else { + hasOverflow = true; + } + if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) { + // Overflow everything if we have an expanded action view and we're + // space constrained. + maxActions = 0; + } + } + + // Reserve a spot for the overflow item if needed. + if (mReserveOverflow && + (hasOverflow || requiredItems + requestedItems > maxActions)) { + maxActions--; + } + maxActions -= requiredItems; + + final SparseBooleanArray seenGroups = mActionButtonGroups; + seenGroups.clear(); + + int cellSize = 0; + int cellsRemaining = 0; + if (mStrictWidthLimit) { + cellsRemaining = widthLimit / mMinCellSize; + final int cellSizeRemaining = widthLimit % mMinCellSize; + cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining; + } + + // Flag as many more requested items as will fit. + for (int i = 0; i < itemsSize; i++) { + MenuItemImpl item = visibleItems.get(i); + + if (item.requiresActionButton()) { + View v = getItemView(item, mScrapActionButtonView, parent); + if (mScrapActionButtonView == null) { + mScrapActionButtonView = v; + } + if (mStrictWidthLimit) { + cellsRemaining -= ActionMenuView.measureChildForCells(v, + cellSize, cellsRemaining, querySpec, 0); + } else { + v.measure(querySpec, querySpec); + } + final int measuredWidth = v.getMeasuredWidth(); + widthLimit -= measuredWidth; + if (firstActionWidth == 0) { + firstActionWidth = measuredWidth; + } + final int groupId = item.getGroupId(); + if (groupId != 0) { + seenGroups.put(groupId, true); + } + item.setIsActionButton(true); + } else if (item.requestsActionButton()) { + // Items in a group with other items that already have an action slot + // can break the max actions rule, but not the width limit. + final int groupId = item.getGroupId(); + final boolean inGroup = seenGroups.get(groupId); + boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0 && + (!mStrictWidthLimit || cellsRemaining > 0); + + if (isAction) { + View v = getItemView(item, mScrapActionButtonView, parent); + if (mScrapActionButtonView == null) { + mScrapActionButtonView = v; + } + if (mStrictWidthLimit) { + final int cells = ActionMenuView.measureChildForCells(v, + cellSize, cellsRemaining, querySpec, 0); + cellsRemaining -= cells; + if (cells == 0) { + isAction = false; + } + } else { + v.measure(querySpec, querySpec); + } + final int measuredWidth = v.getMeasuredWidth(); + widthLimit -= measuredWidth; + if (firstActionWidth == 0) { + firstActionWidth = measuredWidth; + } + + if (mStrictWidthLimit) { + isAction &= widthLimit >= 0; + } else { + // Did this push the entire first item past the limit? + isAction &= widthLimit + firstActionWidth > 0; + } + } + + if (isAction && groupId != 0) { + seenGroups.put(groupId, true); + } else if (inGroup) { + // We broke the width limit. Demote the whole group, they all overflow now. + seenGroups.put(groupId, false); + for (int j = 0; j < i; j++) { + MenuItemImpl areYouMyGroupie = visibleItems.get(j); + if (areYouMyGroupie.getGroupId() == groupId) { + // Give back the action slot + if (areYouMyGroupie.isActionButton()) maxActions++; + areYouMyGroupie.setIsActionButton(false); + } + } + } + + if (isAction) maxActions--; + + item.setIsActionButton(isAction); + } + } + return true; + } + + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + dismissPopupMenus(); + super.onCloseMenu(menu, allMenusAreClosing); + } + + @Override + public Parcelable onSaveInstanceState() { + SavedState state = new SavedState(); + state.openSubMenuId = mOpenSubMenuId; + return state; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState saved = (SavedState) state; + if (saved.openSubMenuId > 0) { + MenuItem item = mMenu.findItem(saved.openSubMenuId); + if (item != null) { + SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + onSubMenuSelected(subMenu); + } + } + } + + @Override + public void onSubUiVisibilityChanged(boolean isVisible) { + if (isVisible) { + // Not a submenu, but treat it like one. + super.onSubMenuSelected(null); + } else { + mMenu.close(false); + } + } + + private static class SavedState implements Parcelable { + public int openSubMenuId; + + SavedState() { + } + + SavedState(Parcel in) { + openSubMenuId = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(openSubMenuId); + } + + @SuppressWarnings("unused") + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + private class OverflowMenuButton extends ImageButton implements ActionMenuChildView, View_HasStateListenerSupport { + private final Set mListeners = new HashSet(); + + public OverflowMenuButton(Context context) { + super(context, null, R.attr.actionOverflowButtonStyle); + + setClickable(true); + setFocusable(true); + setVisibility(VISIBLE); + setEnabled(true); + } + + @Override + public boolean performClick() { + if (super.performClick()) { + return true; + } + + playSoundEffect(SoundEffectConstants.CLICK); + showOverflowMenu(); + return true; + } + + public boolean needsDividerBefore() { + return false; + } + + public boolean needsDividerAfter() { + return false; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + for (View_OnAttachStateChangeListener listener : mListeners) { + listener.onViewAttachedToWindow(this); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (View_OnAttachStateChangeListener listener : mListeners) { + listener.onViewDetachedFromWindow(this); + } + + if (mOverflowPopup != null) mOverflowPopup.dismiss(); + } + + @Override + public void addOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { + mListeners.add(listener); + } + + @Override + public void removeOnAttachStateChangeListener(View_OnAttachStateChangeListener listener) { + mListeners.remove(listener); + } + } + + private class OverflowPopup extends MenuPopupHelper { + public OverflowPopup(Context context, MenuBuilder menu, View anchorView, + boolean overflowOnly) { + super(context, menu, anchorView, overflowOnly); + setCallback(mPopupPresenterCallback); + } + + @Override + public void onDismiss() { + super.onDismiss(); + mMenu.close(); + mOverflowPopup = null; + } + } + + private class ActionButtonSubmenu extends MenuPopupHelper { + //UNUSED private SubMenuBuilder mSubMenu; + + public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) { + super(context, subMenu); + //UNUSED mSubMenu = subMenu; + + MenuItemImpl item = (MenuItemImpl) subMenu.getItem(); + if (!item.isActionButton()) { + // Give a reasonable anchor to nested submenus. + setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton); + } + + setCallback(mPopupPresenterCallback); + + boolean preserveIconSpacing = false; + final int count = subMenu.size(); + for (int i = 0; i < count; i++) { + MenuItem childItem = subMenu.getItem(i); + if (childItem.isVisible() && childItem.getIcon() != null) { + preserveIconSpacing = true; + break; + } + } + setForceShowIcon(preserveIconSpacing); + } + + @Override + public void onDismiss() { + super.onDismiss(); + mActionButtonPopup = null; + mOpenSubMenuId = 0; + } + } + + private class PopupPresenterCallback implements MenuPresenter.Callback { + + @Override + public boolean onOpenSubMenu(MenuBuilder subMenu) { + if (subMenu == null) return false; + + mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId(); + return false; + } + + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + if (menu instanceof SubMenuBuilder) { + ((SubMenuBuilder) menu).getRootMenu().close(false); + } + } + } + + private class OpenOverflowRunnable implements Runnable { + private OverflowPopup mPopup; + + public OpenOverflowRunnable(OverflowPopup popup) { + mPopup = popup; + } + + public void run() { + mMenu.changeMenuMode(); + final View menuView = (View) mMenuView; + if (menuView != null && menuView.getWindowToken() != null && mPopup.tryShow()) { + mOverflowPopup = mPopup; + } + mPostedOpenRunnable = null; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java new file mode 100644 index 000000000..0e3b1ae0d --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuView.java @@ -0,0 +1,575 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.actionbarsherlock.internal.view.menu; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.os.Build; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.widget.LinearLayout; +import com.actionbarsherlock.internal.widget.IcsLinearLayout; + +/** + * @hide + */ +public class ActionMenuView extends IcsLinearLayout implements MenuBuilder.ItemInvoker, MenuView { + //UNUSED private static final String TAG = "ActionMenuView"; + private static final boolean IS_FROYO = Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; + + static final int MIN_CELL_SIZE = 56; // dips + static final int GENERATED_ITEM_PADDING = 4; // dips + + private MenuBuilder mMenu; + + private boolean mReserveOverflow; + private ActionMenuPresenter mPresenter; + private boolean mFormatItems; + private int mFormatItemsWidth; + private int mMinCellSize; + private int mGeneratedItemPadding; + //UNUSED private int mMeasuredExtraWidth; + + private boolean mFirst = true; + + public ActionMenuView(Context context) { + this(context, null); + } + + public ActionMenuView(Context context, AttributeSet attrs) { + super(context, attrs); + setBaselineAligned(false); + final float density = context.getResources().getDisplayMetrics().density; + mMinCellSize = (int) (MIN_CELL_SIZE * density); + mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density); + } + + public void setPresenter(ActionMenuPresenter presenter) { + mPresenter = presenter; + } + + public boolean isExpandedFormat() { + return mFormatItems; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + if (IS_FROYO) { + super.onConfigurationChanged(newConfig); + } + mPresenter.updateMenuView(false); + + if (mPresenter != null && mPresenter.isOverflowMenuShowing()) { + mPresenter.hideOverflowMenu(); + mPresenter.showOverflowMenu(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + //Need to trigger a relayout since we may have been added extremely + //late in the initial rendering (e.g., when contained in a ViewPager). + //See: https://github.com/JakeWharton/ActionBarSherlock/issues/272 + if (!IS_FROYO && mFirst) { + mFirst = false; + requestLayout(); + return; + } + super.onDraw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // If we've been given an exact size to match, apply special formatting during layout. + final boolean wasFormatted = mFormatItems; + mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; + + if (wasFormatted != mFormatItems) { + mFormatItemsWidth = 0; // Reset this when switching modes + } + + // Special formatting can change whether items can fit as action buttons. + // Kick the menu and update presenters when this changes. + final int widthSize = MeasureSpec.getMode(widthMeasureSpec); + if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) { + mFormatItemsWidth = widthSize; + mMenu.onItemsChanged(true); + } + + if (mFormatItems) { + onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + + private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) { + // We already know the width mode is EXACTLY if we're here. + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + final int widthPadding = getPaddingLeft() + getPaddingRight(); + final int heightPadding = getPaddingTop() + getPaddingBottom(); + + widthSize -= widthPadding; + + // Divide the view into cells. + final int cellCount = widthSize / mMinCellSize; + final int cellSizeRemaining = widthSize % mMinCellSize; + + if (cellCount == 0) { + // Give up, nothing fits. + setMeasuredDimension(widthSize, 0); + return; + } + + final int cellSize = mMinCellSize + cellSizeRemaining / cellCount; + + int cellsRemaining = cellCount; + int maxChildHeight = 0; + int maxCellsUsed = 0; + int expandableItemCount = 0; + int visibleItemCount = 0; + boolean hasOverflow = false; + + // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64. + long smallestItemsAt = 0; + + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() == GONE) continue; + + final boolean isGeneratedItem = child instanceof ActionMenuItemView; + visibleItemCount++; + + if (isGeneratedItem) { + // Reset padding for generated menu item views; it may change below + // and views are recycled. + child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0); + } + + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + lp.expanded = false; + lp.extraPixels = 0; + lp.cellsUsed = 0; + lp.expandable = false; + lp.leftMargin = 0; + lp.rightMargin = 0; + lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText(); + + // Overflow always gets 1 cell. No more, no less. + final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining; + + final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, + heightMeasureSpec, heightPadding); + + maxCellsUsed = Math.max(maxCellsUsed, cellsUsed); + if (lp.expandable) expandableItemCount++; + if (lp.isOverflowButton) hasOverflow = true; + + cellsRemaining -= cellsUsed; + maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); + if (cellsUsed == 1) smallestItemsAt |= (1 << i); + } + + // When we have overflow and a single expanded (text) item, we want to try centering it + // visually in the available space even though overflow consumes some of it. + final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2; + + // Divide space for remaining cells if we have items that can expand. + // Try distributing whole leftover cells to smaller items first. + + boolean needsExpansion = false; + while (expandableItemCount > 0 && cellsRemaining > 0) { + int minCells = Integer.MAX_VALUE; + long minCellsAt = 0; // Bit locations are indices of relevant child views + int minCellsItemCount = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + // Don't try to expand items that shouldn't. + if (!lp.expandable) continue; + + // Mark indices of children that can receive an extra cell. + if (lp.cellsUsed < minCells) { + minCells = lp.cellsUsed; + minCellsAt = 1 << i; + minCellsItemCount = 1; + } else if (lp.cellsUsed == minCells) { + minCellsAt |= 1 << i; + minCellsItemCount++; + } + } + + // Items that get expanded will always be in the set of smallest items when we're done. + smallestItemsAt |= minCellsAt; + + if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop. + + // We have enough cells, all minimum size items will be incremented. + minCells++; + + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if ((minCellsAt & (1 << i)) == 0) { + // If this item is already at our small item count, mark it for later. + if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i; + continue; + } + + if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) { + // Add padding to this item such that it centers. + child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0); + } + lp.cellsUsed++; + lp.expanded = true; + cellsRemaining--; + } + + needsExpansion = true; + } + + // Divide any space left that wouldn't divide along cell boundaries + // evenly among the smallest items + + final boolean singleItem = !hasOverflow && visibleItemCount == 1; + if (cellsRemaining > 0 && smallestItemsAt != 0 && + (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) { + float expandCount = Long.bitCount(smallestItemsAt); + + if (!singleItem) { + // The items at the far edges may only expand by half in order to pin to either side. + if ((smallestItemsAt & 1) != 0) { + LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams(); + if (!lp.preventEdgeOffset) expandCount -= 0.5f; + } + if ((smallestItemsAt & (1 << (childCount - 1))) != 0) { + LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams()); + if (!lp.preventEdgeOffset) expandCount -= 0.5f; + } + } + + final int extraPixels = expandCount > 0 ? + (int) (cellsRemaining * cellSize / expandCount) : 0; + + for (int i = 0; i < childCount; i++) { + if ((smallestItemsAt & (1 << i)) == 0) continue; + + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (child instanceof ActionMenuItemView) { + // If this is one of our views, expand and measure at the larger size. + lp.extraPixels = extraPixels; + lp.expanded = true; + if (i == 0 && !lp.preventEdgeOffset) { + // First item gets part of its new padding pushed out of sight. + // The last item will get this implicitly from layout. + lp.leftMargin = -extraPixels / 2; + } + needsExpansion = true; + } else if (lp.isOverflowButton) { + lp.extraPixels = extraPixels; + lp.expanded = true; + lp.rightMargin = -extraPixels / 2; + needsExpansion = true; + } else { + // If we don't know what it is, give it some margins instead + // and let it center within its space. We still want to pin + // against the edges. + if (i != 0) { + lp.leftMargin = extraPixels / 2; + } + if (i != childCount - 1) { + lp.rightMargin = extraPixels / 2; + } + } + } + + cellsRemaining = 0; + } + + // Remeasure any items that have had extra space allocated to them. + if (needsExpansion) { + int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode); + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + if (!lp.expanded) continue; + + final int width = lp.cellsUsed * cellSize + lp.extraPixels; + child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec); + } + } + + if (heightMode != MeasureSpec.EXACTLY) { + heightSize = maxChildHeight; + } + + setMeasuredDimension(widthSize, heightSize); + //UNUSED mMeasuredExtraWidth = cellsRemaining * cellSize; + } + + /** + * Measure a child view to fit within cell-based formatting. The child's width + * will be measured to a whole multiple of cellSize. + * + *

Sets the expandable and cellsUsed fields of LayoutParams. + * + * @param child Child to measure + * @param cellSize Size of one cell + * @param cellsRemaining Number of cells remaining that this view can expand to fill + * @param parentHeightMeasureSpec MeasureSpec used by the parent view + * @param parentHeightPadding Padding present in the parent view + * @return Number of cells this child was measured to occupy + */ + static int measureChildForCells(View child, int cellSize, int cellsRemaining, + int parentHeightMeasureSpec, int parentHeightPadding) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) - + parentHeightPadding; + final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); + final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode); + + int cellsUsed = 0; + if (cellsRemaining > 0) { + final int childWidthSpec = MeasureSpec.makeMeasureSpec( + cellSize * cellsRemaining, MeasureSpec.AT_MOST); + child.measure(childWidthSpec, childHeightSpec); + + final int measuredWidth = child.getMeasuredWidth(); + cellsUsed = measuredWidth / cellSize; + if (measuredWidth % cellSize != 0) cellsUsed++; + } + + final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? + (ActionMenuItemView) child : null; + final boolean expandable = !lp.isOverflowButton && itemView != null && itemView.hasText(); + lp.expandable = expandable; + + lp.cellsUsed = cellsUsed; + final int targetWidth = cellsUsed * cellSize; + child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), + childHeightSpec); + return cellsUsed; + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (!mFormatItems) { + super.onLayout(changed, left, top, right, bottom); + return; + } + + final int childCount = getChildCount(); + final int midVertical = (top + bottom) / 2; + final int dividerWidth = 0;//getDividerWidth(); + int overflowWidth = 0; + //UNUSED int nonOverflowWidth = 0; + int nonOverflowCount = 0; + int widthRemaining = right - left - getPaddingRight() - getPaddingLeft(); + boolean hasOverflow = false; + for (int i = 0; i < childCount; i++) { + final View v = getChildAt(i); + if (v.getVisibility() == GONE) { + continue; + } + + LayoutParams p = (LayoutParams) v.getLayoutParams(); + if (p.isOverflowButton) { + overflowWidth = v.getMeasuredWidth(); + if (hasDividerBeforeChildAt(i)) { + overflowWidth += dividerWidth; + } + + int height = v.getMeasuredHeight(); + int r = getWidth() - getPaddingRight() - p.rightMargin; + int l = r - overflowWidth; + int t = midVertical - (height / 2); + int b = t + height; + v.layout(l, t, r, b); + + widthRemaining -= overflowWidth; + hasOverflow = true; + } else { + final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin; + //UNUSED nonOverflowWidth += size; + widthRemaining -= size; + //if (hasDividerBeforeChildAt(i)) { + //UNUSED nonOverflowWidth += dividerWidth; + //} + nonOverflowCount++; + } + } + + if (childCount == 1 && !hasOverflow) { + // Center a single child + final View v = getChildAt(0); + final int width = v.getMeasuredWidth(); + final int height = v.getMeasuredHeight(); + final int midHorizontal = (right - left) / 2; + final int l = midHorizontal - width / 2; + final int t = midVertical - height / 2; + v.layout(l, t, l + width, t + height); + return; + } + + final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1); + final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0); + + int startLeft = getPaddingLeft(); + for (int i = 0; i < childCount; i++) { + final View v = getChildAt(i); + final LayoutParams lp = (LayoutParams) v.getLayoutParams(); + if (v.getVisibility() == GONE || lp.isOverflowButton) { + continue; + } + + startLeft += lp.leftMargin; + int width = v.getMeasuredWidth(); + int height = v.getMeasuredHeight(); + int t = midVertical - height / 2; + v.layout(startLeft, t, startLeft + width, t + height); + startLeft += width + lp.rightMargin + spacerSize; + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mPresenter.dismissPopupMenus(); + } + + public boolean isOverflowReserved() { + return mReserveOverflow; + } + + public void setOverflowReserved(boolean reserveOverflow) { + mReserveOverflow = reserveOverflow; + } + + @Override + protected LayoutParams generateDefaultLayoutParams() { + LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + params.gravity = Gravity.CENTER_VERTICAL; + return params; + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new LayoutParams(getContext(), attrs); + } + + @Override + protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { + if (p instanceof LayoutParams) { + LayoutParams result = new LayoutParams((LayoutParams) p); + if (result.gravity <= Gravity.NO_GRAVITY) { + result.gravity = Gravity.CENTER_VERTICAL; + } + return result; + } + return generateDefaultLayoutParams(); + } + + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p != null && p instanceof LayoutParams; + } + + public LayoutParams generateOverflowButtonLayoutParams() { + LayoutParams result = generateDefaultLayoutParams(); + result.isOverflowButton = true; + return result; + } + + public boolean invokeItem(MenuItemImpl item) { + return mMenu.performItemAction(item, 0); + } + + public int getWindowAnimations() { + return 0; + } + + public void initialize(MenuBuilder menu) { + mMenu = menu; + } + + //@Override + protected boolean hasDividerBeforeChildAt(int childIndex) { + if (childIndex == 0) { + return false; + } + final View childBefore = getChildAt(childIndex - 1); + final View child = getChildAt(childIndex); + boolean result = false; + if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) { + result |= ((ActionMenuChildView) childBefore).needsDividerAfter(); + } + if (childIndex > 0 && child instanceof ActionMenuChildView) { + result |= ((ActionMenuChildView) child).needsDividerBefore(); + } + return result; + } + + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + return false; + } + + public interface ActionMenuChildView { + public boolean needsDividerBefore(); + public boolean needsDividerAfter(); + } + + public static class LayoutParams extends LinearLayout.LayoutParams { + public boolean isOverflowButton; + public int cellsUsed; + public int extraPixels; + public boolean expandable; + public boolean preventEdgeOffset; + + public boolean expanded; + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + } + + public LayoutParams(LayoutParams other) { + super((LinearLayout.LayoutParams) other); + isOverflowButton = other.isOverflowButton; + } + + public LayoutParams(int width, int height) { + super(width, height); + isOverflowButton = false; + } + + public LayoutParams(int width, int height, boolean isOverflowButton) { + super(width, height); + this.isOverflowButton = isOverflowButton; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java new file mode 100644 index 000000000..6da26f2ae --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/BaseMenuPresenter.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import java.util.ArrayList; +import android.content.Context; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * Base class for MenuPresenters that have a consistent container view and item + * views. Behaves similarly to an AdapterView in that existing item views will + * be reused if possible when items change. + */ +public abstract class BaseMenuPresenter implements MenuPresenter { + private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + + protected Context mSystemContext; + protected Context mContext; + protected MenuBuilder mMenu; + protected LayoutInflater mSystemInflater; + protected LayoutInflater mInflater; + private Callback mCallback; + + private int mMenuLayoutRes; + private int mItemLayoutRes; + + protected MenuView mMenuView; + + private int mId; + + /** + * Construct a new BaseMenuPresenter. + * + * @param context Context for generating system-supplied views + * @param menuLayoutRes Layout resource ID for the menu container view + * @param itemLayoutRes Layout resource ID for a single item view + */ + public BaseMenuPresenter(Context context, int menuLayoutRes, int itemLayoutRes) { + mSystemContext = context; + mSystemInflater = LayoutInflater.from(context); + mMenuLayoutRes = menuLayoutRes; + mItemLayoutRes = itemLayoutRes; + } + + @Override + public void initForMenu(Context context, MenuBuilder menu) { + mContext = context; + mInflater = LayoutInflater.from(mContext); + mMenu = menu; + } + + @Override + public MenuView getMenuView(ViewGroup root) { + if (mMenuView == null) { + mMenuView = (MenuView) mSystemInflater.inflate(mMenuLayoutRes, root, false); + mMenuView.initialize(mMenu); + updateMenuView(true); + } + + return mMenuView; + } + + /** + * Reuses item views when it can + */ + public void updateMenuView(boolean cleared) { + final ViewGroup parent = (ViewGroup) mMenuView; + if (parent == null) return; + + int childIndex = 0; + if (mMenu != null) { + mMenu.flagActionItems(); + ArrayList visibleItems = mMenu.getVisibleItems(); + final int itemCount = visibleItems.size(); + for (int i = 0; i < itemCount; i++) { + MenuItemImpl item = visibleItems.get(i); + if (shouldIncludeItem(childIndex, item)) { + final View convertView = parent.getChildAt(childIndex); + final MenuItemImpl oldItem = convertView instanceof MenuView.ItemView ? + ((MenuView.ItemView) convertView).getItemData() : null; + final View itemView = getItemView(item, convertView, parent); + if (item != oldItem) { + // Don't let old states linger with new data. + itemView.setPressed(false); + if (IS_HONEYCOMB) itemView.jumpDrawablesToCurrentState(); + } + if (itemView != convertView) { + addItemView(itemView, childIndex); + } + childIndex++; + } + } + } + + // Remove leftover views. + while (childIndex < parent.getChildCount()) { + if (!filterLeftoverView(parent, childIndex)) { + childIndex++; + } + } + } + + /** + * Add an item view at the given index. + * + * @param itemView View to add + * @param childIndex Index within the parent to insert at + */ + protected void addItemView(View itemView, int childIndex) { + final ViewGroup currentParent = (ViewGroup) itemView.getParent(); + if (currentParent != null) { + currentParent.removeView(itemView); + } + ((ViewGroup) mMenuView).addView(itemView, childIndex); + } + + /** + * Filter the child view at index and remove it if appropriate. + * @param parent Parent to filter from + * @param childIndex Index to filter + * @return true if the child view at index was removed + */ + protected boolean filterLeftoverView(ViewGroup parent, int childIndex) { + parent.removeViewAt(childIndex); + return true; + } + + public void setCallback(Callback cb) { + mCallback = cb; + } + + /** + * Create a new item view that can be re-bound to other item data later. + * + * @return The new item view + */ + public MenuView.ItemView createItemView(ViewGroup parent) { + return (MenuView.ItemView) mSystemInflater.inflate(mItemLayoutRes, parent, false); + } + + /** + * Prepare an item view for use. See AdapterView for the basic idea at work here. + * This may require creating a new item view, but well-behaved implementations will + * re-use the view passed as convertView if present. The returned view will be populated + * with data from the item parameter. + * + * @param item Item to present + * @param convertView Existing view to reuse + * @param parent Intended parent view - use for inflation. + * @return View that presents the requested menu item + */ + public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) { + MenuView.ItemView itemView; + if (convertView instanceof MenuView.ItemView) { + itemView = (MenuView.ItemView) convertView; + } else { + itemView = createItemView(parent); + } + bindItemView(item, itemView); + return (View) itemView; + } + + /** + * Bind item data to an existing item view. + * + * @param item Item to bind + * @param itemView View to populate with item data + */ + public abstract void bindItemView(MenuItemImpl item, MenuView.ItemView itemView); + + /** + * Filter item by child index and item data. + * + * @param childIndex Indended presentation index of this item + * @param item Item to present + * @return true if this item should be included in this menu presentation; false otherwise + */ + public boolean shouldIncludeItem(int childIndex, MenuItemImpl item) { + return true; + } + + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + if (mCallback != null) { + mCallback.onCloseMenu(menu, allMenusAreClosing); + } + } + + public boolean onSubMenuSelected(SubMenuBuilder menu) { + if (mCallback != null) { + return mCallback.onOpenSubMenu(menu); + } + return false; + } + + public boolean flagActionItems() { + return false; + } + + public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { + return false; + } + + public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { + return false; + } + + public int getId() { + return mId; + } + + public void setId(int id) { + mId = id; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java new file mode 100644 index 000000000..ac25c3736 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ListMenuItemView.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import com.actionbarsherlock.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.TextView; + +/** + * The item view for each item in the ListView-based MenuViews. + */ +public class ListMenuItemView extends LinearLayout implements MenuView.ItemView { + private MenuItemImpl mItemData; + + private ImageView mIconView; + private RadioButton mRadioButton; + private TextView mTitleView; + private CheckBox mCheckBox; + private TextView mShortcutView; + + private Drawable mBackground; + private int mTextAppearance; + private Context mTextAppearanceContext; + private boolean mPreserveIconSpacing; + + //UNUSED private int mMenuType; + + private LayoutInflater mInflater; + + private boolean mForceShowIcon; + + final Context mContext; + + public ListMenuItemView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs); + mContext = context; + + TypedArray a = + context.obtainStyledAttributes( + attrs, R.styleable.SherlockMenuView, defStyle, 0); + + mBackground = a.getDrawable(R.styleable.SherlockMenuView_itemBackground); + mTextAppearance = a.getResourceId(R.styleable. + SherlockMenuView_itemTextAppearance, -1); + mPreserveIconSpacing = a.getBoolean( + R.styleable.SherlockMenuView_preserveIconSpacing, false); + mTextAppearanceContext = context; + + a.recycle(); + } + + public ListMenuItemView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + setBackgroundDrawable(mBackground); + + mTitleView = (TextView) findViewById(R.id.abs__title); + if (mTextAppearance != -1) { + mTitleView.setTextAppearance(mTextAppearanceContext, + mTextAppearance); + } + + mShortcutView = (TextView) findViewById(R.id.abs__shortcut); + } + + public void initialize(MenuItemImpl itemData, int menuType) { + mItemData = itemData; + //UNUSED mMenuType = menuType; + + setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE); + + setTitle(itemData.getTitleForItemView(this)); + setCheckable(itemData.isCheckable()); + setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut()); + setIcon(itemData.getIcon()); + setEnabled(itemData.isEnabled()); + } + + public void setForceShowIcon(boolean forceShow) { + mPreserveIconSpacing = mForceShowIcon = forceShow; + } + + public void setTitle(CharSequence title) { + if (title != null) { + mTitleView.setText(title); + + if (mTitleView.getVisibility() != VISIBLE) mTitleView.setVisibility(VISIBLE); + } else { + if (mTitleView.getVisibility() != GONE) mTitleView.setVisibility(GONE); + } + } + + public MenuItemImpl getItemData() { + return mItemData; + } + + public void setCheckable(boolean checkable) { + + if (!checkable && mRadioButton == null && mCheckBox == null) { + return; + } + + if (mRadioButton == null) { + insertRadioButton(); + } + if (mCheckBox == null) { + insertCheckBox(); + } + + // Depending on whether its exclusive check or not, the checkbox or + // radio button will be the one in use (and the other will be otherCompoundButton) + final CompoundButton compoundButton; + final CompoundButton otherCompoundButton; + + if (mItemData.isExclusiveCheckable()) { + compoundButton = mRadioButton; + otherCompoundButton = mCheckBox; + } else { + compoundButton = mCheckBox; + otherCompoundButton = mRadioButton; + } + + if (checkable) { + compoundButton.setChecked(mItemData.isChecked()); + + final int newVisibility = checkable ? VISIBLE : GONE; + if (compoundButton.getVisibility() != newVisibility) { + compoundButton.setVisibility(newVisibility); + } + + // Make sure the other compound button isn't visible + if (otherCompoundButton.getVisibility() != GONE) { + otherCompoundButton.setVisibility(GONE); + } + } else { + mCheckBox.setVisibility(GONE); + mRadioButton.setVisibility(GONE); + } + } + + public void setChecked(boolean checked) { + CompoundButton compoundButton; + + if (mItemData.isExclusiveCheckable()) { + if (mRadioButton == null) { + insertRadioButton(); + } + compoundButton = mRadioButton; + } else { + if (mCheckBox == null) { + insertCheckBox(); + } + compoundButton = mCheckBox; + } + + compoundButton.setChecked(checked); + } + + public void setShortcut(boolean showShortcut, char shortcutKey) { + final int newVisibility = (showShortcut && mItemData.shouldShowShortcut()) + ? VISIBLE : GONE; + + if (newVisibility == VISIBLE) { + mShortcutView.setText(mItemData.getShortcutLabel()); + } + + if (mShortcutView.getVisibility() != newVisibility) { + mShortcutView.setVisibility(newVisibility); + } + } + + public void setIcon(Drawable icon) { + final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon; + if (!showIcon && !mPreserveIconSpacing) { + return; + } + + if (mIconView == null && icon == null && !mPreserveIconSpacing) { + return; + } + + if (mIconView == null) { + insertIconView(); + } + + if (icon != null || mPreserveIconSpacing) { + mIconView.setImageDrawable(showIcon ? icon : null); + + if (mIconView.getVisibility() != VISIBLE) { + mIconView.setVisibility(VISIBLE); + } + } else { + mIconView.setVisibility(GONE); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mIconView != null && mPreserveIconSpacing) { + // Enforce minimum icon spacing + ViewGroup.LayoutParams lp = getLayoutParams(); + LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); + if (lp.height > 0 && iconLp.width <= 0) { + iconLp.width = lp.height; + } + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + private void insertIconView() { + LayoutInflater inflater = getInflater(); + mIconView = (ImageView) inflater.inflate(R.layout.abs__list_menu_item_icon, + this, false); + addView(mIconView, 0); + } + + private void insertRadioButton() { + LayoutInflater inflater = getInflater(); + mRadioButton = + (RadioButton) inflater.inflate(R.layout.abs__list_menu_item_radio, + this, false); + addView(mRadioButton); + } + + private void insertCheckBox() { + LayoutInflater inflater = getInflater(); + mCheckBox = + (CheckBox) inflater.inflate(R.layout.abs__list_menu_item_checkbox, + this, false); + addView(mCheckBox); + } + + public boolean prefersCondensedTitle() { + return false; + } + + public boolean showsIcon() { + return mForceShowIcon; + } + + private LayoutInflater getInflater() { + if (mInflater == null) { + mInflater = LayoutInflater.from(mContext); + } + return mInflater; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java new file mode 100644 index 000000000..179b8f037 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuBuilder.java @@ -0,0 +1,1335 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Parcelable; +import android.util.SparseArray; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.View; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +/** + * Implementation of the {@link android.view.Menu} interface for creating a + * standard menu UI. + */ +public class MenuBuilder implements Menu { + //UNUSED private static final String TAG = "MenuBuilder"; + + private static final String PRESENTER_KEY = "android:menu:presenters"; + private static final String ACTION_VIEW_STATES_KEY = "android:menu:actionviewstates"; + private static final String EXPANDED_ACTION_VIEW_ID = "android:menu:expandedactionview"; + + private static final int[] sCategoryToOrder = new int[] { + 1, /* No category */ + 4, /* CONTAINER */ + 5, /* SYSTEM */ + 3, /* SECONDARY */ + 2, /* ALTERNATIVE */ + 0, /* SELECTED_ALTERNATIVE */ + }; + + private final Context mContext; + private final Resources mResources; + + /** + * Whether the shortcuts should be qwerty-accessible. Use isQwertyMode() + * instead of accessing this directly. + */ + private boolean mQwertyMode; + + /** + * Whether the shortcuts should be visible on menus. Use isShortcutsVisible() + * instead of accessing this directly. + */ + private boolean mShortcutsVisible; + + /** + * Callback that will receive the various menu-related events generated by + * this class. Use getCallback to get a reference to the callback. + */ + private Callback mCallback; + + /** Contains all of the items for this menu */ + private ArrayList mItems; + + /** Contains only the items that are currently visible. This will be created/refreshed from + * {@link #getVisibleItems()} */ + private ArrayList mVisibleItems; + /** + * Whether or not the items (or any one item's shown state) has changed since it was last + * fetched from {@link #getVisibleItems()} + */ + private boolean mIsVisibleItemsStale; + + /** + * Contains only the items that should appear in the Action Bar, if present. + */ + private ArrayList mActionItems; + /** + * Contains items that should NOT appear in the Action Bar, if present. + */ + private ArrayList mNonActionItems; + + /** + * Whether or not the items (or any one item's action state) has changed since it was + * last fetched. + */ + private boolean mIsActionItemsStale; + + /** + * Default value for how added items should show in the action list. + */ + private int mDefaultShowAsAction = MenuItem.SHOW_AS_ACTION_NEVER; + + /** + * Current use case is Context Menus: As Views populate the context menu, each one has + * extra information that should be passed along. This is the current menu info that + * should be set on all items added to this menu. + */ + private ContextMenuInfo mCurrentMenuInfo; + + /** Header title for menu types that have a header (context and submenus) */ + CharSequence mHeaderTitle; + /** Header icon for menu types that have a header and support icons (context) */ + Drawable mHeaderIcon; + /** Header custom view for menu types that have a header and support custom views (context) */ + View mHeaderView; + + /** + * Contains the state of the View hierarchy for all menu views when the menu + * was frozen. + */ + //UNUSED private SparseArray mFrozenViewStates; + + /** + * Prevents onItemsChanged from doing its junk, useful for batching commands + * that may individually call onItemsChanged. + */ + private boolean mPreventDispatchingItemsChanged = false; + private boolean mItemsChangedWhileDispatchPrevented = false; + + private boolean mOptionalIconsVisible = false; + + private boolean mIsClosing = false; + + private ArrayList mTempShortcutItemList = new ArrayList(); + + private CopyOnWriteArrayList> mPresenters = + new CopyOnWriteArrayList>(); + + /** + * Currently expanded menu item; must be collapsed when we clear. + */ + private MenuItemImpl mExpandedItem; + + /** + * Called by menu to notify of close and selection changes. + */ + public interface Callback { + /** + * Called when a menu item is selected. + * @param menu The menu that is the parent of the item + * @param item The menu item that is selected + * @return whether the menu item selection was handled + */ + public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item); + + /** + * Called when the mode of the menu changes (for example, from icon to expanded). + * + * @param menu the menu that has changed modes + */ + public void onMenuModeChange(MenuBuilder menu); + } + + /** + * Called by menu items to execute their associated action + */ + public interface ItemInvoker { + public boolean invokeItem(MenuItemImpl item); + } + + public MenuBuilder(Context context) { + mContext = context; + mResources = context.getResources(); + + mItems = new ArrayList(); + + mVisibleItems = new ArrayList(); + mIsVisibleItemsStale = true; + + mActionItems = new ArrayList(); + mNonActionItems = new ArrayList(); + mIsActionItemsStale = true; + + setShortcutsVisibleInner(true); + } + + public MenuBuilder setDefaultShowAsAction(int defaultShowAsAction) { + mDefaultShowAsAction = defaultShowAsAction; + return this; + } + + /** + * Add a presenter to this menu. This will only hold a WeakReference; + * you do not need to explicitly remove a presenter, but you can using + * {@link #removeMenuPresenter(MenuPresenter)}. + * + * @param presenter The presenter to add + */ + public void addMenuPresenter(MenuPresenter presenter) { + mPresenters.add(new WeakReference(presenter)); + presenter.initForMenu(mContext, this); + mIsActionItemsStale = true; + } + + /** + * Remove a presenter from this menu. That presenter will no longer + * receive notifications of updates to this menu's data. + * + * @param presenter The presenter to remove + */ + public void removeMenuPresenter(MenuPresenter presenter) { + for (WeakReference ref : mPresenters) { + final MenuPresenter item = ref.get(); + if (item == null || item == presenter) { + mPresenters.remove(ref); + } + } + } + + private void dispatchPresenterUpdate(boolean cleared) { + if (mPresenters.isEmpty()) return; + + stopDispatchingItemsChanged(); + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + presenter.updateMenuView(cleared); + } + } + startDispatchingItemsChanged(); + } + + private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) { + if (mPresenters.isEmpty()) return false; + + boolean result = false; + + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else if (!result) { + result = presenter.onSubMenuSelected(subMenu); + } + } + return result; + } + + private void dispatchSaveInstanceState(Bundle outState) { + if (mPresenters.isEmpty()) return; + + SparseArray presenterStates = new SparseArray(); + + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + final int id = presenter.getId(); + if (id > 0) { + final Parcelable state = presenter.onSaveInstanceState(); + if (state != null) { + presenterStates.put(id, state); + } + } + } + } + + outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates); + } + + private void dispatchRestoreInstanceState(Bundle state) { + SparseArray presenterStates = state.getSparseParcelableArray(PRESENTER_KEY); + + if (presenterStates == null || mPresenters.isEmpty()) return; + + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + final int id = presenter.getId(); + if (id > 0) { + Parcelable parcel = presenterStates.get(id); + if (parcel != null) { + presenter.onRestoreInstanceState(parcel); + } + } + } + } + } + + public void savePresenterStates(Bundle outState) { + dispatchSaveInstanceState(outState); + } + + public void restorePresenterStates(Bundle state) { + dispatchRestoreInstanceState(state); + } + + public void saveActionViewStates(Bundle outStates) { + SparseArray viewStates = null; + + final int itemCount = size(); + for (int i = 0; i < itemCount; i++) { + final MenuItem item = getItem(i); + final View v = item.getActionView(); + if (v != null && v.getId() != View.NO_ID) { + if (viewStates == null) { + viewStates = new SparseArray(); + } + v.saveHierarchyState(viewStates); + if (item.isActionViewExpanded()) { + outStates.putInt(EXPANDED_ACTION_VIEW_ID, item.getItemId()); + } + } + if (item.hasSubMenu()) { + final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + subMenu.saveActionViewStates(outStates); + } + } + + if (viewStates != null) { + outStates.putSparseParcelableArray(getActionViewStatesKey(), viewStates); + } + } + + public void restoreActionViewStates(Bundle states) { + if (states == null) { + return; + } + + SparseArray viewStates = states.getSparseParcelableArray( + getActionViewStatesKey()); + + final int itemCount = size(); + for (int i = 0; i < itemCount; i++) { + final MenuItem item = getItem(i); + final View v = item.getActionView(); + if (v != null && v.getId() != View.NO_ID) { + v.restoreHierarchyState(viewStates); + } + if (item.hasSubMenu()) { + final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + subMenu.restoreActionViewStates(states); + } + } + + final int expandedId = states.getInt(EXPANDED_ACTION_VIEW_ID); + if (expandedId > 0) { + MenuItem itemToExpand = findItem(expandedId); + if (itemToExpand != null) { + itemToExpand.expandActionView(); + } + } + } + + protected String getActionViewStatesKey() { + return ACTION_VIEW_STATES_KEY; + } + + public void setCallback(Callback cb) { + mCallback = cb; + } + + /** + * Adds an item to the menu. The other add methods funnel to this. + */ + private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) { + final int ordering = getOrdering(categoryOrder); + + final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder, + ordering, title, mDefaultShowAsAction); + + if (mCurrentMenuInfo != null) { + // Pass along the current menu info + item.setMenuInfo(mCurrentMenuInfo); + } + + mItems.add(findInsertIndex(mItems, ordering), item); + onItemsChanged(true); + + return item; + } + + public MenuItem add(CharSequence title) { + return addInternal(0, 0, 0, title); + } + + public MenuItem add(int titleRes) { + return addInternal(0, 0, 0, mResources.getString(titleRes)); + } + + public MenuItem add(int group, int id, int categoryOrder, CharSequence title) { + return addInternal(group, id, categoryOrder, title); + } + + public MenuItem add(int group, int id, int categoryOrder, int title) { + return addInternal(group, id, categoryOrder, mResources.getString(title)); + } + + public SubMenu addSubMenu(CharSequence title) { + return addSubMenu(0, 0, 0, title); + } + + public SubMenu addSubMenu(int titleRes) { + return addSubMenu(0, 0, 0, mResources.getString(titleRes)); + } + + public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) { + final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title); + final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item); + item.setSubMenu(subMenu); + + return subMenu; + } + + public SubMenu addSubMenu(int group, int id, int categoryOrder, int title) { + return addSubMenu(group, id, categoryOrder, mResources.getString(title)); + } + + public int addIntentOptions(int group, int id, int categoryOrder, ComponentName caller, + Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { + PackageManager pm = mContext.getPackageManager(); + final List lri = + pm.queryIntentActivityOptions(caller, specifics, intent, 0); + final int N = lri != null ? lri.size() : 0; + + if ((flags & FLAG_APPEND_TO_GROUP) == 0) { + removeGroup(group); + } + + for (int i=0; i= 0) { + outSpecificItems[ri.specificIndex] = item; + } + } + + return N; + } + + public void removeItem(int id) { + removeItemAtInt(findItemIndex(id), true); + } + + public void removeGroup(int group) { + final int i = findGroupIndex(group); + + if (i >= 0) { + final int maxRemovable = mItems.size() - i; + int numRemoved = 0; + while ((numRemoved++ < maxRemovable) && (mItems.get(i).getGroupId() == group)) { + // Don't force update for each one, this method will do it at the end + removeItemAtInt(i, false); + } + + // Notify menu views + onItemsChanged(true); + } + } + + /** + * Remove the item at the given index and optionally forces menu views to + * update. + * + * @param index The index of the item to be removed. If this index is + * invalid an exception is thrown. + * @param updateChildrenOnMenuViews Whether to force update on menu views. + * Please make sure you eventually call this after your batch of + * removals. + */ + private void removeItemAtInt(int index, boolean updateChildrenOnMenuViews) { + if ((index < 0) || (index >= mItems.size())) return; + + mItems.remove(index); + + if (updateChildrenOnMenuViews) onItemsChanged(true); + } + + public void removeItemAt(int index) { + removeItemAtInt(index, true); + } + + public void clearAll() { + mPreventDispatchingItemsChanged = true; + clear(); + clearHeader(); + mPreventDispatchingItemsChanged = false; + mItemsChangedWhileDispatchPrevented = false; + onItemsChanged(true); + } + + public void clear() { + if (mExpandedItem != null) { + collapseItemActionView(mExpandedItem); + } + mItems.clear(); + + onItemsChanged(true); + } + + void setExclusiveItemChecked(MenuItem item) { + final int group = item.getGroupId(); + + final int N = mItems.size(); + for (int i = 0; i < N; i++) { + MenuItemImpl curItem = mItems.get(i); + if (curItem.getGroupId() == group) { + if (!curItem.isExclusiveCheckable()) continue; + if (!curItem.isCheckable()) continue; + + // Check the item meant to be checked, uncheck the others (that are in the group) + curItem.setCheckedInt(curItem == item); + } + } + } + + public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { + final int N = mItems.size(); + + for (int i = 0; i < N; i++) { + MenuItemImpl item = mItems.get(i); + if (item.getGroupId() == group) { + item.setExclusiveCheckable(exclusive); + item.setCheckable(checkable); + } + } + } + + public void setGroupVisible(int group, boolean visible) { + final int N = mItems.size(); + + // We handle the notification of items being changed ourselves, so we use setVisibleInt rather + // than setVisible and at the end notify of items being changed + + boolean changedAtLeastOneItem = false; + for (int i = 0; i < N; i++) { + MenuItemImpl item = mItems.get(i); + if (item.getGroupId() == group) { + if (item.setVisibleInt(visible)) changedAtLeastOneItem = true; + } + } + + if (changedAtLeastOneItem) onItemsChanged(true); + } + + public void setGroupEnabled(int group, boolean enabled) { + final int N = mItems.size(); + + for (int i = 0; i < N; i++) { + MenuItemImpl item = mItems.get(i); + if (item.getGroupId() == group) { + item.setEnabled(enabled); + } + } + } + + public boolean hasVisibleItems() { + final int size = size(); + + for (int i = 0; i < size; i++) { + MenuItemImpl item = mItems.get(i); + if (item.isVisible()) { + return true; + } + } + + return false; + } + + public MenuItem findItem(int id) { + final int size = size(); + for (int i = 0; i < size; i++) { + MenuItemImpl item = mItems.get(i); + if (item.getItemId() == id) { + return item; + } else if (item.hasSubMenu()) { + MenuItem possibleItem = item.getSubMenu().findItem(id); + + if (possibleItem != null) { + return possibleItem; + } + } + } + + return null; + } + + public int findItemIndex(int id) { + final int size = size(); + + for (int i = 0; i < size; i++) { + MenuItemImpl item = mItems.get(i); + if (item.getItemId() == id) { + return i; + } + } + + return -1; + } + + public int findGroupIndex(int group) { + return findGroupIndex(group, 0); + } + + public int findGroupIndex(int group, int start) { + final int size = size(); + + if (start < 0) { + start = 0; + } + + for (int i = start; i < size; i++) { + final MenuItemImpl item = mItems.get(i); + + if (item.getGroupId() == group) { + return i; + } + } + + return -1; + } + + public int size() { + return mItems.size(); + } + + /** {@inheritDoc} */ + public MenuItem getItem(int index) { + return mItems.get(index); + } + + public boolean isShortcutKey(int keyCode, KeyEvent event) { + return findItemWithShortcutForKey(keyCode, event) != null; + } + + public void setQwertyMode(boolean isQwerty) { + mQwertyMode = isQwerty; + + onItemsChanged(false); + } + + /** + * Returns the ordering across all items. This will grab the category from + * the upper bits, find out how to order the category with respect to other + * categories, and combine it with the lower bits. + * + * @param categoryOrder The category order for a particular item (if it has + * not been or/add with a category, the default category is + * assumed). + * @return An ordering integer that can be used to order this item across + * all the items (even from other categories). + */ + private static int getOrdering(int categoryOrder) { + final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT; + + if (index < 0 || index >= sCategoryToOrder.length) { + throw new IllegalArgumentException("order does not contain a valid category."); + } + + return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK); + } + + /** + * @return whether the menu shortcuts are in qwerty mode or not + */ + boolean isQwertyMode() { + return mQwertyMode; + } + + /** + * Sets whether the shortcuts should be visible on menus. Devices without hardware + * key input will never make shortcuts visible even if this method is passed 'true'. + * + * @param shortcutsVisible Whether shortcuts should be visible (if true and a + * menu item does not have a shortcut defined, that item will + * still NOT show a shortcut) + */ + public void setShortcutsVisible(boolean shortcutsVisible) { + if (mShortcutsVisible == shortcutsVisible) return; + + setShortcutsVisibleInner(shortcutsVisible); + onItemsChanged(false); + } + + private void setShortcutsVisibleInner(boolean shortcutsVisible) { + mShortcutsVisible = shortcutsVisible + && mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS + && mResources.getBoolean( + R.bool.abs__config_showMenuShortcutsWhenKeyboardPresent); + } + + /** + * @return Whether shortcuts should be visible on menus. + */ + public boolean isShortcutsVisible() { + return mShortcutsVisible; + } + + Resources getResources() { + return mResources; + } + + public Context getContext() { + return mContext; + } + + boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) { + return mCallback != null && mCallback.onMenuItemSelected(menu, item); + } + + /** + * Dispatch a mode change event to this menu's callback. + */ + public void changeMenuMode() { + if (mCallback != null) { + mCallback.onMenuModeChange(this); + } + } + + private static int findInsertIndex(ArrayList items, int ordering) { + for (int i = items.size() - 1; i >= 0; i--) { + MenuItemImpl item = items.get(i); + if (item.getOrdering() <= ordering) { + return i + 1; + } + } + + return 0; + } + + public boolean performShortcut(int keyCode, KeyEvent event, int flags) { + final MenuItemImpl item = findItemWithShortcutForKey(keyCode, event); + + boolean handled = false; + + if (item != null) { + handled = performItemAction(item, flags); + } + + if ((flags & FLAG_ALWAYS_PERFORM_CLOSE) != 0) { + close(true); + } + + return handled; + } + + /* + * This function will return all the menu and sub-menu items that can + * be directly (the shortcut directly corresponds) and indirectly + * (the ALT-enabled char corresponds to the shortcut) associated + * with the keyCode. + */ + @SuppressWarnings("deprecation") + void findItemsWithShortcutForKey(List items, int keyCode, KeyEvent event) { + final boolean qwerty = isQwertyMode(); + final int metaState = event.getMetaState(); + final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); + // Get the chars associated with the keyCode (i.e using any chording combo) + final boolean isKeyCodeMapped = event.getKeyData(possibleChars); + // The delete key is not mapped to '\b' so we treat it specially + if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) { + return; + } + + // Look for an item whose shortcut is this key. + final int N = mItems.size(); + for (int i = 0; i < N; i++) { + MenuItemImpl item = mItems.get(i); + if (item.hasSubMenu()) { + ((MenuBuilder)item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event); + } + final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut(); + if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0) && + (shortcutChar != 0) && + (shortcutChar == possibleChars.meta[0] + || shortcutChar == possibleChars.meta[2] + || (qwerty && shortcutChar == '\b' && + keyCode == KeyEvent.KEYCODE_DEL)) && + item.isEnabled()) { + items.add(item); + } + } + } + + /* + * We want to return the menu item associated with the key, but if there is no + * ambiguity (i.e. there is only one menu item corresponding to the key) we want + * to return it even if it's not an exact match; this allow the user to + * _not_ use the ALT key for example, making the use of shortcuts slightly more + * user-friendly. An example is on the G1, '!' and '1' are on the same key, and + * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut). + * + * On the other hand, if two (or more) shortcuts corresponds to the same key, + * we have to only return the exact match. + */ + @SuppressWarnings("deprecation") + MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) { + // Get all items that can be associated directly or indirectly with the keyCode + ArrayList items = mTempShortcutItemList; + items.clear(); + findItemsWithShortcutForKey(items, keyCode, event); + + if (items.isEmpty()) { + return null; + } + + final int metaState = event.getMetaState(); + final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData(); + // Get the chars associated with the keyCode (i.e using any chording combo) + event.getKeyData(possibleChars); + + // If we have only one element, we can safely returns it + final int size = items.size(); + if (size == 1) { + return items.get(0); + } + + final boolean qwerty = isQwertyMode(); + // If we found more than one item associated with the key, + // we have to return the exact match + for (int i = 0; i < size; i++) { + final MenuItemImpl item = items.get(i); + final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : + item.getNumericShortcut(); + if ((shortcutChar == possibleChars.meta[0] && + (metaState & KeyEvent.META_ALT_ON) == 0) + || (shortcutChar == possibleChars.meta[2] && + (metaState & KeyEvent.META_ALT_ON) != 0) + || (qwerty && shortcutChar == '\b' && + keyCode == KeyEvent.KEYCODE_DEL)) { + return item; + } + } + return null; + } + + public boolean performIdentifierAction(int id, int flags) { + // Look for an item whose identifier is the id. + return performItemAction(findItem(id), flags); + } + + public boolean performItemAction(MenuItem item, int flags) { + MenuItemImpl itemImpl = (MenuItemImpl) item; + + if (itemImpl == null || !itemImpl.isEnabled()) { + return false; + } + + boolean invoked = itemImpl.invoke(); + + if (itemImpl.hasCollapsibleActionView()) { + invoked |= itemImpl.expandActionView(); + if (invoked) close(true); + } else if (item.hasSubMenu()) { + close(false); + + final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); + final ActionProvider provider = item.getActionProvider(); + if (provider != null && provider.hasSubMenu()) { + provider.onPrepareSubMenu(subMenu); + } + invoked |= dispatchSubMenuSelected(subMenu); + if (!invoked) close(true); + } else { + if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) { + close(true); + } + } + + return invoked; + } + + /** + * Closes the visible menu. + * + * @param allMenusAreClosing Whether the menus are completely closing (true), + * or whether there is another menu coming in this menu's place + * (false). For example, if the menu is closing because a + * sub menu is about to be shown, allMenusAreClosing + * is false. + */ + final void close(boolean allMenusAreClosing) { + if (mIsClosing) return; + + mIsClosing = true; + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + presenter.onCloseMenu(this, allMenusAreClosing); + } + } + mIsClosing = false; + } + + /** {@inheritDoc} */ + public void close() { + close(true); + } + + /** + * Called when an item is added or removed. + * + * @param structureChanged true if the menu structure changed, + * false if only item properties changed. + * (Visibility is a structural property since it affects layout.) + */ + void onItemsChanged(boolean structureChanged) { + if (!mPreventDispatchingItemsChanged) { + if (structureChanged) { + mIsVisibleItemsStale = true; + mIsActionItemsStale = true; + } + + dispatchPresenterUpdate(structureChanged); + } else { + mItemsChangedWhileDispatchPrevented = true; + } + } + + /** + * Stop dispatching item changed events to presenters until + * {@link #startDispatchingItemsChanged()} is called. Useful when + * many menu operations are going to be performed as a batch. + */ + public void stopDispatchingItemsChanged() { + if (!mPreventDispatchingItemsChanged) { + mPreventDispatchingItemsChanged = true; + mItemsChangedWhileDispatchPrevented = false; + } + } + + public void startDispatchingItemsChanged() { + mPreventDispatchingItemsChanged = false; + + if (mItemsChangedWhileDispatchPrevented) { + mItemsChangedWhileDispatchPrevented = false; + onItemsChanged(true); + } + } + + /** + * Called by {@link MenuItemImpl} when its visible flag is changed. + * @param item The item that has gone through a visibility change. + */ + void onItemVisibleChanged(MenuItemImpl item) { + // Notify of items being changed + mIsVisibleItemsStale = true; + onItemsChanged(true); + } + + /** + * Called by {@link MenuItemImpl} when its action request status is changed. + * @param item The item that has gone through a change in action request status. + */ + void onItemActionRequestChanged(MenuItemImpl item) { + // Notify of items being changed + mIsActionItemsStale = true; + onItemsChanged(true); + } + + ArrayList getVisibleItems() { + if (!mIsVisibleItemsStale) return mVisibleItems; + + // Refresh the visible items + mVisibleItems.clear(); + + final int itemsSize = mItems.size(); + MenuItemImpl item; + for (int i = 0; i < itemsSize; i++) { + item = mItems.get(i); + if (item.isVisible()) mVisibleItems.add(item); + } + + mIsVisibleItemsStale = false; + mIsActionItemsStale = true; + + return mVisibleItems; + } + + /** + * This method determines which menu items get to be 'action items' that will appear + * in an action bar and which items should be 'overflow items' in a secondary menu. + * The rules are as follows: + * + *

Items are considered for inclusion in the order specified within the menu. + * There is a limit of mMaxActionItems as a total count, optionally including the overflow + * menu button itself. This is a soft limit; if an item shares a group ID with an item + * previously included as an action item, the new item will stay with its group and become + * an action item itself even if it breaks the max item count limit. This is done to + * limit the conceptual complexity of the items presented within an action bar. Only a few + * unrelated concepts should be presented to the user in this space, and groups are treated + * as a single concept. + * + *

There is also a hard limit of consumed measurable space: mActionWidthLimit. This + * limit may be broken by a single item that exceeds the remaining space, but no further + * items may be added. If an item that is part of a group cannot fit within the remaining + * measured width, the entire group will be demoted to overflow. This is done to ensure room + * for navigation and other affordances in the action bar as well as reduce general UI clutter. + * + *

The space freed by demoting a full group cannot be consumed by future menu items. + * Once items begin to overflow, all future items become overflow items as well. This is + * to avoid inadvertent reordering that may break the app's intended design. + */ + public void flagActionItems() { + if (!mIsActionItemsStale) { + return; + } + + // Presenters flag action items as needed. + boolean flagged = false; + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else { + flagged |= presenter.flagActionItems(); + } + } + + if (flagged) { + mActionItems.clear(); + mNonActionItems.clear(); + ArrayList visibleItems = getVisibleItems(); + final int itemsSize = visibleItems.size(); + for (int i = 0; i < itemsSize; i++) { + MenuItemImpl item = visibleItems.get(i); + if (item.isActionButton()) { + mActionItems.add(item); + } else { + mNonActionItems.add(item); + } + } + } else { + // Nobody flagged anything, everything is a non-action item. + // (This happens during a first pass with no action-item presenters.) + mActionItems.clear(); + mNonActionItems.clear(); + mNonActionItems.addAll(getVisibleItems()); + } + mIsActionItemsStale = false; + } + + ArrayList getActionItems() { + flagActionItems(); + return mActionItems; + } + + ArrayList getNonActionItems() { + flagActionItems(); + return mNonActionItems; + } + + public void clearHeader() { + mHeaderIcon = null; + mHeaderTitle = null; + mHeaderView = null; + + onItemsChanged(false); + } + + private void setHeaderInternal(final int titleRes, final CharSequence title, final int iconRes, + final Drawable icon, final View view) { + final Resources r = getResources(); + + if (view != null) { + mHeaderView = view; + + // If using a custom view, then the title and icon aren't used + mHeaderTitle = null; + mHeaderIcon = null; + } else { + if (titleRes > 0) { + mHeaderTitle = r.getText(titleRes); + } else if (title != null) { + mHeaderTitle = title; + } + + if (iconRes > 0) { + mHeaderIcon = r.getDrawable(iconRes); + } else if (icon != null) { + mHeaderIcon = icon; + } + + // If using the title or icon, then a custom view isn't used + mHeaderView = null; + } + + // Notify of change + onItemsChanged(false); + } + + /** + * Sets the header's title. This replaces the header view. Called by the + * builder-style methods of subclasses. + * + * @param title The new title. + * @return This MenuBuilder so additional setters can be called. + */ + protected MenuBuilder setHeaderTitleInt(CharSequence title) { + setHeaderInternal(0, title, 0, null, null); + return this; + } + + /** + * Sets the header's title. This replaces the header view. Called by the + * builder-style methods of subclasses. + * + * @param titleRes The new title (as a resource ID). + * @return This MenuBuilder so additional setters can be called. + */ + protected MenuBuilder setHeaderTitleInt(int titleRes) { + setHeaderInternal(titleRes, null, 0, null, null); + return this; + } + + /** + * Sets the header's icon. This replaces the header view. Called by the + * builder-style methods of subclasses. + * + * @param icon The new icon. + * @return This MenuBuilder so additional setters can be called. + */ + protected MenuBuilder setHeaderIconInt(Drawable icon) { + setHeaderInternal(0, null, 0, icon, null); + return this; + } + + /** + * Sets the header's icon. This replaces the header view. Called by the + * builder-style methods of subclasses. + * + * @param iconRes The new icon (as a resource ID). + * @return This MenuBuilder so additional setters can be called. + */ + protected MenuBuilder setHeaderIconInt(int iconRes) { + setHeaderInternal(0, null, iconRes, null, null); + return this; + } + + /** + * Sets the header's view. This replaces the title and icon. Called by the + * builder-style methods of subclasses. + * + * @param view The new view. + * @return This MenuBuilder so additional setters can be called. + */ + protected MenuBuilder setHeaderViewInt(View view) { + setHeaderInternal(0, null, 0, null, view); + return this; + } + + public CharSequence getHeaderTitle() { + return mHeaderTitle; + } + + public Drawable getHeaderIcon() { + return mHeaderIcon; + } + + public View getHeaderView() { + return mHeaderView; + } + + /** + * Gets the root menu (if this is a submenu, find its root menu). + * @return The root menu. + */ + public MenuBuilder getRootMenu() { + return this; + } + + /** + * Sets the current menu info that is set on all items added to this menu + * (until this is called again with different menu info, in which case that + * one will be added to all subsequent item additions). + * + * @param menuInfo The extra menu information to add. + */ + public void setCurrentMenuInfo(ContextMenuInfo menuInfo) { + mCurrentMenuInfo = menuInfo; + } + + void setOptionalIconsVisible(boolean visible) { + mOptionalIconsVisible = visible; + } + + boolean getOptionalIconsVisible() { + return mOptionalIconsVisible; + } + + public boolean expandItemActionView(MenuItemImpl item) { + if (mPresenters.isEmpty()) return false; + + boolean expanded = false; + + stopDispatchingItemsChanged(); + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else if ((expanded = presenter.expandItemActionView(this, item))) { + break; + } + } + startDispatchingItemsChanged(); + + if (expanded) { + mExpandedItem = item; + } + return expanded; + } + + public boolean collapseItemActionView(MenuItemImpl item) { + if (mPresenters.isEmpty() || mExpandedItem != item) return false; + + boolean collapsed = false; + + stopDispatchingItemsChanged(); + for (WeakReference ref : mPresenters) { + final MenuPresenter presenter = ref.get(); + if (presenter == null) { + mPresenters.remove(ref); + } else if ((collapsed = presenter.collapseItemActionView(this, item))) { + break; + } + } + startDispatchingItemsChanged(); + + if (collapsed) { + mExpandedItem = null; + } + return collapsed; + } + + public MenuItemImpl getExpandedItem() { + return mExpandedItem; + } + + public boolean bindNativeOverflow(android.view.Menu menu, android.view.MenuItem.OnMenuItemClickListener listener, HashMap map) { + final List nonActionItems = getNonActionItems(); + if (nonActionItems == null || nonActionItems.size() == 0) { + return false; + } + + boolean visible = false; + menu.clear(); + for (MenuItemImpl nonActionItem : nonActionItems) { + if (!nonActionItem.isVisible()) { + continue; + } + visible = true; + + android.view.MenuItem nativeItem; + if (nonActionItem.hasSubMenu()) { + android.view.SubMenu nativeSub = menu.addSubMenu(nonActionItem.getGroupId(), nonActionItem.getItemId(), + nonActionItem.getOrder(), nonActionItem.getTitle()); + + SubMenuBuilder subMenu = (SubMenuBuilder)nonActionItem.getSubMenu(); + for (MenuItemImpl subItem : subMenu.getVisibleItems()) { + android.view.MenuItem nativeSubItem = nativeSub.add(subItem.getGroupId(), subItem.getItemId(), + subItem.getOrder(), subItem.getTitle()); + + nativeSubItem.setIcon(subItem.getIcon()); + nativeSubItem.setOnMenuItemClickListener(listener); + nativeSubItem.setEnabled(subItem.isEnabled()); + nativeSubItem.setIntent(subItem.getIntent()); + nativeSubItem.setNumericShortcut(subItem.getNumericShortcut()); + nativeSubItem.setAlphabeticShortcut(subItem.getAlphabeticShortcut()); + nativeSubItem.setTitleCondensed(subItem.getTitleCondensed()); + nativeSubItem.setCheckable(subItem.isCheckable()); + nativeSubItem.setChecked(subItem.isChecked()); + + if (subItem.isExclusiveCheckable()) { + nativeSub.setGroupCheckable(subItem.getGroupId(), true, true); + } + + map.put(nativeSubItem, subItem); + } + + nativeItem = nativeSub.getItem(); + } else { + nativeItem = menu.add(nonActionItem.getGroupId(), nonActionItem.getItemId(), + nonActionItem.getOrder(), nonActionItem.getTitle()); + } + nativeItem.setIcon(nonActionItem.getIcon()); + nativeItem.setOnMenuItemClickListener(listener); + nativeItem.setEnabled(nonActionItem.isEnabled()); + nativeItem.setIntent(nonActionItem.getIntent()); + nativeItem.setNumericShortcut(nonActionItem.getNumericShortcut()); + nativeItem.setAlphabeticShortcut(nonActionItem.getAlphabeticShortcut()); + nativeItem.setTitleCondensed(nonActionItem.getTitleCondensed()); + nativeItem.setCheckable(nonActionItem.isCheckable()); + nativeItem.setChecked(nonActionItem.isChecked()); + + if (nonActionItem.isExclusiveCheckable()) { + menu.setGroupCheckable(nonActionItem.getGroupId(), true, true); + } + + map.put(nativeItem, nonActionItem); + } + return visible; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java new file mode 100644 index 000000000..f5359fb40 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemImpl.java @@ -0,0 +1,647 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewDebug; +import android.widget.LinearLayout; + +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +/** + * @hide + */ +public final class MenuItemImpl implements MenuItem { + private static final String TAG = "MenuItemImpl"; + + private static final int SHOW_AS_ACTION_MASK = SHOW_AS_ACTION_NEVER | + SHOW_AS_ACTION_IF_ROOM | + SHOW_AS_ACTION_ALWAYS; + + private final int mId; + private final int mGroup; + private final int mCategoryOrder; + private final int mOrdering; + private CharSequence mTitle; + private CharSequence mTitleCondensed; + private Intent mIntent; + private char mShortcutNumericChar; + private char mShortcutAlphabeticChar; + + /** The icon's drawable which is only created as needed */ + private Drawable mIconDrawable; + /** + * The icon's resource ID which is used to get the Drawable when it is + * needed (if the Drawable isn't already obtained--only one of the two is + * needed). + */ + private int mIconResId = NO_ICON; + + /** The menu to which this item belongs */ + private MenuBuilder mMenu; + /** If this item should launch a sub menu, this is the sub menu to launch */ + private SubMenuBuilder mSubMenu; + + private Runnable mItemCallback; + private MenuItem.OnMenuItemClickListener mClickListener; + + private int mFlags = ENABLED; + private static final int CHECKABLE = 0x00000001; + private static final int CHECKED = 0x00000002; + private static final int EXCLUSIVE = 0x00000004; + private static final int HIDDEN = 0x00000008; + private static final int ENABLED = 0x00000010; + private static final int IS_ACTION = 0x00000020; + + private int mShowAsAction = SHOW_AS_ACTION_NEVER; + + private View mActionView; + private ActionProvider mActionProvider; + private OnActionExpandListener mOnActionExpandListener; + private boolean mIsActionViewExpanded = false; + + /** Used for the icon resource ID if this item does not have an icon */ + static final int NO_ICON = 0; + + /** + * Current use case is for context menu: Extra information linked to the + * View that added this item to the context menu. + */ + private ContextMenuInfo mMenuInfo; + + private static String sPrependShortcutLabel; + private static String sEnterShortcutLabel; + private static String sDeleteShortcutLabel; + private static String sSpaceShortcutLabel; + + + /** + * Instantiates this menu item. + * + * @param menu + * @param group Item ordering grouping control. The item will be added after + * all other items whose order is <= this number, and before any + * that are larger than it. This can also be used to define + * groups of items for batch state changes. Normally use 0. + * @param id Unique item ID. Use 0 if you do not need a unique ID. + * @param categoryOrder The ordering for this item. + * @param title The text to display for the item. + */ + MenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering, + CharSequence title, int showAsAction) { + + /* TODO if (sPrependShortcutLabel == null) { + // This is instantiated from the UI thread, so no chance of sync issues + sPrependShortcutLabel = menu.getContext().getResources().getString( + com.android.internal.R.string.prepend_shortcut_label); + sEnterShortcutLabel = menu.getContext().getResources().getString( + com.android.internal.R.string.menu_enter_shortcut_label); + sDeleteShortcutLabel = menu.getContext().getResources().getString( + com.android.internal.R.string.menu_delete_shortcut_label); + sSpaceShortcutLabel = menu.getContext().getResources().getString( + com.android.internal.R.string.menu_space_shortcut_label); + }*/ + + mMenu = menu; + mId = id; + mGroup = group; + mCategoryOrder = categoryOrder; + mOrdering = ordering; + mTitle = title; + mShowAsAction = showAsAction; + } + + /** + * Invokes the item by calling various listeners or callbacks. + * + * @return true if the invocation was handled, false otherwise + */ + public boolean invoke() { + if (mClickListener != null && + mClickListener.onMenuItemClick(this)) { + return true; + } + + if (mMenu.dispatchMenuItemSelected(mMenu.getRootMenu(), this)) { + return true; + } + + if (mItemCallback != null) { + mItemCallback.run(); + return true; + } + + if (mIntent != null) { + try { + mMenu.getContext().startActivity(mIntent); + return true; + } catch (ActivityNotFoundException e) { + Log.e(TAG, "Can't find activity to handle intent; ignoring", e); + } + } + + if (mActionProvider != null && mActionProvider.onPerformDefaultAction()) { + return true; + } + + return false; + } + + public boolean isEnabled() { + return (mFlags & ENABLED) != 0; + } + + public MenuItem setEnabled(boolean enabled) { + if (enabled) { + mFlags |= ENABLED; + } else { + mFlags &= ~ENABLED; + } + + mMenu.onItemsChanged(false); + + return this; + } + + public int getGroupId() { + return mGroup; + } + + @ViewDebug.CapturedViewProperty + public int getItemId() { + return mId; + } + + public int getOrder() { + return mCategoryOrder; + } + + public int getOrdering() { + return mOrdering; + } + + public Intent getIntent() { + return mIntent; + } + + public MenuItem setIntent(Intent intent) { + mIntent = intent; + return this; + } + + Runnable getCallback() { + return mItemCallback; + } + + public MenuItem setCallback(Runnable callback) { + mItemCallback = callback; + return this; + } + + public char getAlphabeticShortcut() { + return mShortcutAlphabeticChar; + } + + public MenuItem setAlphabeticShortcut(char alphaChar) { + if (mShortcutAlphabeticChar == alphaChar) return this; + + mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); + + mMenu.onItemsChanged(false); + + return this; + } + + public char getNumericShortcut() { + return mShortcutNumericChar; + } + + public MenuItem setNumericShortcut(char numericChar) { + if (mShortcutNumericChar == numericChar) return this; + + mShortcutNumericChar = numericChar; + + mMenu.onItemsChanged(false); + + return this; + } + + public MenuItem setShortcut(char numericChar, char alphaChar) { + mShortcutNumericChar = numericChar; + mShortcutAlphabeticChar = Character.toLowerCase(alphaChar); + + mMenu.onItemsChanged(false); + + return this; + } + + /** + * @return The active shortcut (based on QWERTY-mode of the menu). + */ + char getShortcut() { + return (mMenu.isQwertyMode() ? mShortcutAlphabeticChar : mShortcutNumericChar); + } + + /** + * @return The label to show for the shortcut. This includes the chording + * key (for example 'Menu+a'). Also, any non-human readable + * characters should be human readable (for example 'Menu+enter'). + */ + String getShortcutLabel() { + + char shortcut = getShortcut(); + if (shortcut == 0) { + return ""; + } + + StringBuilder sb = new StringBuilder(sPrependShortcutLabel); + switch (shortcut) { + + case '\n': + sb.append(sEnterShortcutLabel); + break; + + case '\b': + sb.append(sDeleteShortcutLabel); + break; + + case ' ': + sb.append(sSpaceShortcutLabel); + break; + + default: + sb.append(shortcut); + break; + } + + return sb.toString(); + } + + /** + * @return Whether this menu item should be showing shortcuts (depends on + * whether the menu should show shortcuts and whether this item has + * a shortcut defined) + */ + boolean shouldShowShortcut() { + // Show shortcuts if the menu is supposed to show shortcuts AND this item has a shortcut + return mMenu.isShortcutsVisible() && (getShortcut() != 0); + } + + public SubMenu getSubMenu() { + return mSubMenu; + } + + public boolean hasSubMenu() { + return mSubMenu != null; + } + + void setSubMenu(SubMenuBuilder subMenu) { + mSubMenu = subMenu; + + subMenu.setHeaderTitle(getTitle()); + } + + @ViewDebug.CapturedViewProperty + public CharSequence getTitle() { + return mTitle; + } + + /** + * Gets the title for a particular {@link ItemView} + * + * @param itemView The ItemView that is receiving the title + * @return Either the title or condensed title based on what the ItemView + * prefers + */ + CharSequence getTitleForItemView(MenuView.ItemView itemView) { + return ((itemView != null) && itemView.prefersCondensedTitle()) + ? getTitleCondensed() + : getTitle(); + } + + public MenuItem setTitle(CharSequence title) { + mTitle = title; + + mMenu.onItemsChanged(false); + + if (mSubMenu != null) { + mSubMenu.setHeaderTitle(title); + } + + return this; + } + + public MenuItem setTitle(int title) { + return setTitle(mMenu.getContext().getString(title)); + } + + public CharSequence getTitleCondensed() { + return mTitleCondensed != null ? mTitleCondensed : mTitle; + } + + public MenuItem setTitleCondensed(CharSequence title) { + mTitleCondensed = title; + + // Could use getTitle() in the loop below, but just cache what it would do here + if (title == null) { + title = mTitle; + } + + mMenu.onItemsChanged(false); + + return this; + } + + public Drawable getIcon() { + if (mIconDrawable != null) { + return mIconDrawable; + } + + if (mIconResId != NO_ICON) { + return mMenu.getResources().getDrawable(mIconResId); + } + + return null; + } + + public MenuItem setIcon(Drawable icon) { + mIconResId = NO_ICON; + mIconDrawable = icon; + mMenu.onItemsChanged(false); + + return this; + } + + public MenuItem setIcon(int iconResId) { + mIconDrawable = null; + mIconResId = iconResId; + + // If we have a view, we need to push the Drawable to them + mMenu.onItemsChanged(false); + + return this; + } + + public boolean isCheckable() { + return (mFlags & CHECKABLE) == CHECKABLE; + } + + public MenuItem setCheckable(boolean checkable) { + final int oldFlags = mFlags; + mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0); + if (oldFlags != mFlags) { + mMenu.onItemsChanged(false); + } + + return this; + } + + public void setExclusiveCheckable(boolean exclusive) { + mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0); + } + + public boolean isExclusiveCheckable() { + return (mFlags & EXCLUSIVE) != 0; + } + + public boolean isChecked() { + return (mFlags & CHECKED) == CHECKED; + } + + public MenuItem setChecked(boolean checked) { + if ((mFlags & EXCLUSIVE) != 0) { + // Call the method on the Menu since it knows about the others in this + // exclusive checkable group + mMenu.setExclusiveItemChecked(this); + } else { + setCheckedInt(checked); + } + + return this; + } + + void setCheckedInt(boolean checked) { + final int oldFlags = mFlags; + mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0); + if (oldFlags != mFlags) { + mMenu.onItemsChanged(false); + } + } + + public boolean isVisible() { + return (mFlags & HIDDEN) == 0; + } + + /** + * Changes the visibility of the item. This method DOES NOT notify the + * parent menu of a change in this item, so this should only be called from + * methods that will eventually trigger this change. If unsure, use {@link #setVisible(boolean)} + * instead. + * + * @param shown Whether to show (true) or hide (false). + * @return Whether the item's shown state was changed + */ + boolean setVisibleInt(boolean shown) { + final int oldFlags = mFlags; + mFlags = (mFlags & ~HIDDEN) | (shown ? 0 : HIDDEN); + return oldFlags != mFlags; + } + + public MenuItem setVisible(boolean shown) { + // Try to set the shown state to the given state. If the shown state was changed + // (i.e. the previous state isn't the same as given state), notify the parent menu that + // the shown state has changed for this item + if (setVisibleInt(shown)) mMenu.onItemVisibleChanged(this); + + return this; + } + + public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener clickListener) { + mClickListener = clickListener; + return this; + } + + @Override + public String toString() { + return mTitle.toString(); + } + + void setMenuInfo(ContextMenuInfo menuInfo) { + mMenuInfo = menuInfo; + } + + public ContextMenuInfo getMenuInfo() { + return mMenuInfo; + } + + public void actionFormatChanged() { + mMenu.onItemActionRequestChanged(this); + } + + /** + * @return Whether the menu should show icons for menu items. + */ + public boolean shouldShowIcon() { + return mMenu.getOptionalIconsVisible(); + } + + public boolean isActionButton() { + return (mFlags & IS_ACTION) == IS_ACTION; + } + + public boolean requestsActionButton() { + return (mShowAsAction & SHOW_AS_ACTION_IF_ROOM) == SHOW_AS_ACTION_IF_ROOM; + } + + public boolean requiresActionButton() { + return (mShowAsAction & SHOW_AS_ACTION_ALWAYS) == SHOW_AS_ACTION_ALWAYS; + } + + public void setIsActionButton(boolean isActionButton) { + if (isActionButton) { + mFlags |= IS_ACTION; + } else { + mFlags &= ~IS_ACTION; + } + } + + public boolean showsTextAsAction() { + return (mShowAsAction & SHOW_AS_ACTION_WITH_TEXT) == SHOW_AS_ACTION_WITH_TEXT; + } + + public void setShowAsAction(int actionEnum) { + switch (actionEnum & SHOW_AS_ACTION_MASK) { + case SHOW_AS_ACTION_ALWAYS: + case SHOW_AS_ACTION_IF_ROOM: + case SHOW_AS_ACTION_NEVER: + // Looks good! + break; + + default: + // Mutually exclusive options selected! + throw new IllegalArgumentException("SHOW_AS_ACTION_ALWAYS, SHOW_AS_ACTION_IF_ROOM," + + " and SHOW_AS_ACTION_NEVER are mutually exclusive."); + } + mShowAsAction = actionEnum; + mMenu.onItemActionRequestChanged(this); + } + + public MenuItem setActionView(View view) { + mActionView = view; + mActionProvider = null; + if (view != null && view.getId() == View.NO_ID && mId > 0) { + view.setId(mId); + } + mMenu.onItemActionRequestChanged(this); + return this; + } + + public MenuItem setActionView(int resId) { + final Context context = mMenu.getContext(); + final LayoutInflater inflater = LayoutInflater.from(context); + setActionView(inflater.inflate(resId, new LinearLayout(context), false)); + return this; + } + + public View getActionView() { + if (mActionView != null) { + return mActionView; + } else if (mActionProvider != null) { + mActionView = mActionProvider.onCreateActionView(); + return mActionView; + } else { + return null; + } + } + + public ActionProvider getActionProvider() { + return mActionProvider; + } + + public MenuItem setActionProvider(ActionProvider actionProvider) { + mActionView = null; + mActionProvider = actionProvider; + mMenu.onItemsChanged(true); // Measurement can be changed + return this; + } + + @Override + public MenuItem setShowAsActionFlags(int actionEnum) { + setShowAsAction(actionEnum); + return this; + } + + @Override + public boolean expandActionView() { + if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0 || mActionView == null) { + return false; + } + + if (mOnActionExpandListener == null || + mOnActionExpandListener.onMenuItemActionExpand(this)) { + return mMenu.expandItemActionView(this); + } + + return false; + } + + @Override + public boolean collapseActionView() { + if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0) { + return false; + } + if (mActionView == null) { + // We're already collapsed if we have no action view. + return true; + } + + if (mOnActionExpandListener == null || + mOnActionExpandListener.onMenuItemActionCollapse(this)) { + return mMenu.collapseItemActionView(this); + } + + return false; + } + + @Override + public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { + mOnActionExpandListener = listener; + return this; + } + + public boolean hasCollapsibleActionView() { + return (mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) != 0 && mActionView != null; + } + + public void setActionViewExpanded(boolean isExpanded) { + mIsActionViewExpanded = isExpanded; + mMenu.onItemsChanged(false); + } + + public boolean isActionViewExpanded() { + return mIsActionViewExpanded; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java new file mode 100644 index 000000000..aaf2997b7 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuItemWrapper.java @@ -0,0 +1,310 @@ +package com.actionbarsherlock.internal.view.menu; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.View; +import com.actionbarsherlock.internal.view.ActionProviderWrapper; +import com.actionbarsherlock.internal.widget.CollapsibleActionViewWrapper; +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.CollapsibleActionView; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +public class MenuItemWrapper implements MenuItem, android.view.MenuItem.OnMenuItemClickListener { + private final android.view.MenuItem mNativeItem; + private SubMenu mSubMenu = null; + private OnMenuItemClickListener mMenuItemClickListener = null; + private OnActionExpandListener mActionExpandListener = null; + private android.view.MenuItem.OnActionExpandListener mNativeActionExpandListener = null; + + + public MenuItemWrapper(android.view.MenuItem nativeItem) { + if (nativeItem == null) { + throw new IllegalStateException("Wrapped menu item cannot be null."); + } + mNativeItem = nativeItem; + } + + + @Override + public int getItemId() { + return mNativeItem.getItemId(); + } + + @Override + public int getGroupId() { + return mNativeItem.getGroupId(); + } + + @Override + public int getOrder() { + return mNativeItem.getOrder(); + } + + @Override + public MenuItem setTitle(CharSequence title) { + mNativeItem.setTitle(title); + return this; + } + + @Override + public MenuItem setTitle(int title) { + mNativeItem.setTitle(title); + return this; + } + + @Override + public CharSequence getTitle() { + return mNativeItem.getTitle(); + } + + @Override + public MenuItem setTitleCondensed(CharSequence title) { + mNativeItem.setTitleCondensed(title); + return this; + } + + @Override + public CharSequence getTitleCondensed() { + return mNativeItem.getTitleCondensed(); + } + + @Override + public MenuItem setIcon(Drawable icon) { + mNativeItem.setIcon(icon); + return this; + } + + @Override + public MenuItem setIcon(int iconRes) { + mNativeItem.setIcon(iconRes); + return this; + } + + @Override + public Drawable getIcon() { + return mNativeItem.getIcon(); + } + + @Override + public MenuItem setIntent(Intent intent) { + mNativeItem.setIntent(intent); + return this; + } + + @Override + public Intent getIntent() { + return mNativeItem.getIntent(); + } + + @Override + public MenuItem setShortcut(char numericChar, char alphaChar) { + mNativeItem.setShortcut(numericChar, alphaChar); + return this; + } + + @Override + public MenuItem setNumericShortcut(char numericChar) { + mNativeItem.setNumericShortcut(numericChar); + return this; + } + + @Override + public char getNumericShortcut() { + return mNativeItem.getNumericShortcut(); + } + + @Override + public MenuItem setAlphabeticShortcut(char alphaChar) { + mNativeItem.setAlphabeticShortcut(alphaChar); + return this; + } + + @Override + public char getAlphabeticShortcut() { + return mNativeItem.getAlphabeticShortcut(); + } + + @Override + public MenuItem setCheckable(boolean checkable) { + mNativeItem.setCheckable(checkable); + return this; + } + + @Override + public boolean isCheckable() { + return mNativeItem.isCheckable(); + } + + @Override + public MenuItem setChecked(boolean checked) { + mNativeItem.setChecked(checked); + return this; + } + + @Override + public boolean isChecked() { + return mNativeItem.isChecked(); + } + + @Override + public MenuItem setVisible(boolean visible) { + mNativeItem.setVisible(visible); + return this; + } + + @Override + public boolean isVisible() { + return mNativeItem.isVisible(); + } + + @Override + public MenuItem setEnabled(boolean enabled) { + mNativeItem.setEnabled(enabled); + return this; + } + + @Override + public boolean isEnabled() { + return mNativeItem.isEnabled(); + } + + @Override + public boolean hasSubMenu() { + return mNativeItem.hasSubMenu(); + } + + @Override + public SubMenu getSubMenu() { + if (hasSubMenu() && (mSubMenu == null)) { + mSubMenu = new SubMenuWrapper(mNativeItem.getSubMenu()); + } + return mSubMenu; + } + + @Override + public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) { + mMenuItemClickListener = menuItemClickListener; + //Register ourselves as the listener to proxy + mNativeItem.setOnMenuItemClickListener(this); + return this; + } + + @Override + public boolean onMenuItemClick(android.view.MenuItem item) { + if (mMenuItemClickListener != null) { + return mMenuItemClickListener.onMenuItemClick(this); + } + return false; + } + + @Override + public ContextMenuInfo getMenuInfo() { + return mNativeItem.getMenuInfo(); + } + + @Override + public void setShowAsAction(int actionEnum) { + mNativeItem.setShowAsAction(actionEnum); + } + + @Override + public MenuItem setShowAsActionFlags(int actionEnum) { + mNativeItem.setShowAsActionFlags(actionEnum); + return this; + } + + @Override + public MenuItem setActionView(View view) { + if (view != null && view instanceof CollapsibleActionView) { + view = new CollapsibleActionViewWrapper(view); + } + mNativeItem.setActionView(view); + return this; + } + + @Override + public MenuItem setActionView(int resId) { + //Allow the native menu to inflate the resource + mNativeItem.setActionView(resId); + if (resId != 0) { + //Get newly created view + View view = mNativeItem.getActionView(); + if (view instanceof CollapsibleActionView) { + //Wrap it and re-set it + mNativeItem.setActionView(new CollapsibleActionViewWrapper(view)); + } + } + return this; + } + + @Override + public View getActionView() { + View actionView = mNativeItem.getActionView(); + if (actionView instanceof CollapsibleActionViewWrapper) { + return ((CollapsibleActionViewWrapper)actionView).unwrap(); + } + return actionView; + } + + @Override + public MenuItem setActionProvider(ActionProvider actionProvider) { + mNativeItem.setActionProvider(new ActionProviderWrapper(actionProvider)); + return this; + } + + @Override + public ActionProvider getActionProvider() { + android.view.ActionProvider nativeProvider = mNativeItem.getActionProvider(); + if (nativeProvider != null && nativeProvider instanceof ActionProviderWrapper) { + return ((ActionProviderWrapper)nativeProvider).unwrap(); + } + return null; + } + + @Override + public boolean expandActionView() { + return mNativeItem.expandActionView(); + } + + @Override + public boolean collapseActionView() { + return mNativeItem.collapseActionView(); + } + + @Override + public boolean isActionViewExpanded() { + return mNativeItem.isActionViewExpanded(); + } + + @Override + public MenuItem setOnActionExpandListener(OnActionExpandListener listener) { + mActionExpandListener = listener; + + if (mNativeActionExpandListener == null) { + mNativeActionExpandListener = new android.view.MenuItem.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(android.view.MenuItem menuItem) { + if (mActionExpandListener != null) { + return mActionExpandListener.onMenuItemActionExpand(MenuItemWrapper.this); + } + return false; + } + + @Override + public boolean onMenuItemActionCollapse(android.view.MenuItem menuItem) { + if (mActionExpandListener != null) { + return mActionExpandListener.onMenuItemActionCollapse(MenuItemWrapper.this); + } + return false; + } + }; + + //Register our inner-class as the listener to proxy method calls + mNativeItem.setOnActionExpandListener(mNativeActionExpandListener); + } + + return this; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java new file mode 100644 index 000000000..f030de310 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPopupHelper.java @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import java.util.ArrayList; +import android.content.Context; +import android.content.res.Resources; +import android.database.DataSetObserver; +import android.os.Parcelable; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; +import android.widget.ListAdapter; +import android.widget.PopupWindow; +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.view.View_HasStateListenerSupport; +import com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener; +import com.actionbarsherlock.internal.widget.IcsListPopupWindow; +import com.actionbarsherlock.view.MenuItem; + +/** + * Presents a menu as a small, simple popup anchored to another view. + * @hide + */ +public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener, + ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener, + View_OnAttachStateChangeListener, MenuPresenter { + //UNUSED private static final String TAG = "MenuPopupHelper"; + + static final int ITEM_LAYOUT = R.layout.abs__popup_menu_item_layout; + + private Context mContext; + private LayoutInflater mInflater; + private IcsListPopupWindow mPopup; + private MenuBuilder mMenu; + private int mPopupMaxWidth; + private View mAnchorView; + private boolean mOverflowOnly; + private ViewTreeObserver mTreeObserver; + + private MenuAdapter mAdapter; + + private Callback mPresenterCallback; + + boolean mForceShowIcon; + + private ViewGroup mMeasureParent; + + public MenuPopupHelper(Context context, MenuBuilder menu) { + this(context, menu, null, false); + } + + public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) { + this(context, menu, anchorView, false); + } + + public MenuPopupHelper(Context context, MenuBuilder menu, + View anchorView, boolean overflowOnly) { + mContext = context; + mInflater = LayoutInflater.from(context); + mMenu = menu; + mOverflowOnly = overflowOnly; + + final Resources res = context.getResources(); + mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2, + res.getDimensionPixelSize(R.dimen.abs__config_prefDialogWidth)); + + mAnchorView = anchorView; + + menu.addMenuPresenter(this); + } + + public void setAnchorView(View anchor) { + mAnchorView = anchor; + } + + public void setForceShowIcon(boolean forceShow) { + mForceShowIcon = forceShow; + } + + public void show() { + if (!tryShow()) { + throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); + } + } + + public boolean tryShow() { + mPopup = new IcsListPopupWindow(mContext, null, R.attr.popupMenuStyle); + mPopup.setOnDismissListener(this); + mPopup.setOnItemClickListener(this); + + mAdapter = new MenuAdapter(mMenu); + mPopup.setAdapter(mAdapter); + mPopup.setModal(true); + + View anchor = mAnchorView; + if (anchor != null) { + final boolean addGlobalListener = mTreeObserver == null; + mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest + if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this); + ((View_HasStateListenerSupport)anchor).addOnAttachStateChangeListener(this); + mPopup.setAnchorView(anchor); + } else { + return false; + } + + mPopup.setContentWidth(Math.min(measureContentWidth(mAdapter), mPopupMaxWidth)); + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); + mPopup.show(); + mPopup.getListView().setOnKeyListener(this); + return true; + } + + public void dismiss() { + if (isShowing()) { + mPopup.dismiss(); + } + } + + public void onDismiss() { + mPopup = null; + mMenu.close(); + if (mTreeObserver != null) { + if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver(); + mTreeObserver.removeGlobalOnLayoutListener(this); + mTreeObserver = null; + } + ((View_HasStateListenerSupport)mAnchorView).removeOnAttachStateChangeListener(this); + } + + public boolean isShowing() { + return mPopup != null && mPopup.isShowing(); + } + + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + MenuAdapter adapter = mAdapter; + adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0); + } + + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) { + dismiss(); + return true; + } + return false; + } + + private int measureContentWidth(ListAdapter adapter) { + // Menus don't tend to be long, so this is more sane than it looks. + int width = 0; + View itemView = null; + int itemType = 0; + final int widthMeasureSpec = + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final int heightMeasureSpec = + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final int count = adapter.getCount(); + for (int i = 0; i < count; i++) { + final int positionType = adapter.getItemViewType(i); + if (positionType != itemType) { + itemType = positionType; + itemView = null; + } + if (mMeasureParent == null) { + mMeasureParent = new FrameLayout(mContext); + } + itemView = adapter.getView(i, itemView, mMeasureParent); + itemView.measure(widthMeasureSpec, heightMeasureSpec); + width = Math.max(width, itemView.getMeasuredWidth()); + } + return width; + } + + @Override + public void onGlobalLayout() { + if (isShowing()) { + final View anchor = mAnchorView; + if (anchor == null || !anchor.isShown()) { + dismiss(); + } else if (isShowing()) { + // Recompute window size and position + mPopup.show(); + } + } + } + + @Override + public void onViewAttachedToWindow(View v) { + } + + @Override + public void onViewDetachedFromWindow(View v) { + if (mTreeObserver != null) { + if (!mTreeObserver.isAlive()) mTreeObserver = v.getViewTreeObserver(); + mTreeObserver.removeGlobalOnLayoutListener(this); + } + ((View_HasStateListenerSupport)v).removeOnAttachStateChangeListener(this); + } + + @Override + public void initForMenu(Context context, MenuBuilder menu) { + // Don't need to do anything; we added as a presenter in the constructor. + } + + @Override + public MenuView getMenuView(ViewGroup root) { + throw new UnsupportedOperationException("MenuPopupHelpers manage their own views"); + } + + @Override + public void updateMenuView(boolean cleared) { + if (mAdapter != null) mAdapter.notifyDataSetChanged(); + } + + @Override + public void setCallback(Callback cb) { + mPresenterCallback = cb; + } + + @Override + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + if (subMenu.hasVisibleItems()) { + MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false); + subPopup.setCallback(mPresenterCallback); + + boolean preserveIconSpacing = false; + final int count = subMenu.size(); + for (int i = 0; i < count; i++) { + MenuItem childItem = subMenu.getItem(i); + if (childItem.isVisible() && childItem.getIcon() != null) { + preserveIconSpacing = true; + break; + } + } + subPopup.setForceShowIcon(preserveIconSpacing); + + if (subPopup.tryShow()) { + if (mPresenterCallback != null) { + mPresenterCallback.onOpenSubMenu(subMenu); + } + return true; + } + } + return false; + } + + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + // Only care about the (sub)menu we're presenting. + if (menu != mMenu) return; + + dismiss(); + if (mPresenterCallback != null) { + mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); + } + } + + @Override + public boolean flagActionItems() { + return false; + } + + public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { + return false; + } + + public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { + return false; + } + + @Override + public int getId() { + return 0; + } + + @Override + public Parcelable onSaveInstanceState() { + return null; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + } + + private class MenuAdapter extends BaseAdapter { + private MenuBuilder mAdapterMenu; + private int mExpandedIndex = -1; + + public MenuAdapter(MenuBuilder menu) { + mAdapterMenu = menu; + registerDataSetObserver(new ExpandedIndexObserver()); + findExpandedIndex(); + } + + public int getCount() { + ArrayList items = mOverflowOnly ? + mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); + if (mExpandedIndex < 0) { + return items.size(); + } + return items.size() - 1; + } + + public MenuItemImpl getItem(int position) { + ArrayList items = mOverflowOnly ? + mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); + if (mExpandedIndex >= 0 && position >= mExpandedIndex) { + position++; + } + return items.get(position); + } + + public long getItemId(int position) { + // Since a menu item's ID is optional, we'll use the position as an + // ID for the item in the AdapterView + return position; + } + + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); + } + + MenuView.ItemView itemView = (MenuView.ItemView) convertView; + if (mForceShowIcon) { + ((ListMenuItemView) convertView).setForceShowIcon(true); + } + itemView.initialize(getItem(position), 0); + return convertView; + } + + void findExpandedIndex() { + final MenuItemImpl expandedItem = mMenu.getExpandedItem(); + if (expandedItem != null) { + final ArrayList items = mMenu.getNonActionItems(); + final int count = items.size(); + for (int i = 0; i < count; i++) { + final MenuItemImpl item = items.get(i); + if (item == expandedItem) { + mExpandedIndex = i; + return; + } + } + } + mExpandedIndex = -1; + } + } + + private class ExpandedIndexObserver extends DataSetObserver { + @Override + public void onChanged() { + mAdapter.findExpandedIndex(); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java new file mode 100644 index 000000000..c3f35472c --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuPresenter.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import android.content.Context; +import android.os.Parcelable; +import android.view.ViewGroup; + +/** + * A MenuPresenter is responsible for building views for a Menu object. + * It takes over some responsibility from the old style monolithic MenuBuilder class. + */ +public interface MenuPresenter { + /** + * Called by menu implementation to notify another component of open/close events. + */ + public interface Callback { + /** + * Called when a menu is closing. + * @param menu + * @param allMenusAreClosing + */ + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing); + + /** + * Called when a submenu opens. Useful for notifying the application + * of menu state so that it does not attempt to hide the action bar + * while a submenu is open or similar. + * + * @param subMenu Submenu currently being opened + * @return true if the Callback will handle presenting the submenu, false if + * the presenter should attempt to do so. + */ + public boolean onOpenSubMenu(MenuBuilder subMenu); + } + + /** + * Initialize this presenter for the given context and menu. + * This method is called by MenuBuilder when a presenter is + * added. See {@link MenuBuilder#addMenuPresenter(MenuPresenter)} + * + * @param context Context for this presenter; used for view creation and resource management + * @param menu Menu to host + */ + public void initForMenu(Context context, MenuBuilder menu); + + /** + * Retrieve a MenuView to display the menu specified in + * {@link #initForMenu(Context, Menu)}. + * + * @param root Intended parent of the MenuView. + * @return A freshly created MenuView. + */ + public MenuView getMenuView(ViewGroup root); + + /** + * Update the menu UI in response to a change. Called by + * MenuBuilder during the normal course of operation. + * + * @param cleared true if the menu was entirely cleared + */ + public void updateMenuView(boolean cleared); + + /** + * Set a callback object that will be notified of menu events + * related to this specific presentation. + * @param cb Callback that will be notified of future events + */ + public void setCallback(Callback cb); + + /** + * Called by Menu implementations to indicate that a submenu item + * has been selected. An active Callback should be notified, and + * if applicable the presenter should present the submenu. + * + * @param subMenu SubMenu being opened + * @return true if the the event was handled, false otherwise. + */ + public boolean onSubMenuSelected(SubMenuBuilder subMenu); + + /** + * Called by Menu implementations to indicate that a menu or submenu is + * closing. Presenter implementations should close the representation + * of the menu indicated as necessary and notify a registered callback. + * + * @param menu Menu or submenu that is closing. + * @param allMenusAreClosing True if all associated menus are closing. + */ + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing); + + /** + * Called by Menu implementations to flag items that will be shown as actions. + * @return true if this presenter changed the action status of any items. + */ + public boolean flagActionItems(); + + /** + * Called when a menu item with a collapsable action view should expand its action view. + * + * @param menu Menu containing the item to be expanded + * @param item Item to be expanded + * @return true if this presenter expanded the action view, false otherwise. + */ + public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item); + + /** + * Called when a menu item with a collapsable action view should collapse its action view. + * + * @param menu Menu containing the item to be collapsed + * @param item Item to be collapsed + * @return true if this presenter collapsed the action view, false otherwise. + */ + public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item); + + /** + * Returns an ID for determining how to save/restore instance state. + * @return a valid ID value. + */ + public int getId(); + + /** + * Returns a Parcelable describing the current state of the presenter. + * It will be passed to the {@link #onRestoreInstanceState(Parcelable)} + * method of the presenter sharing the same ID later. + * @return The saved instance state + */ + public Parcelable onSaveInstanceState(); + + /** + * Supplies the previously saved instance state to be restored. + * @param state The previously saved instance state + */ + public void onRestoreInstanceState(Parcelable state); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java new file mode 100644 index 000000000..323ba2d88 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuView.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import android.graphics.drawable.Drawable; + +/** + * Minimal interface for a menu view. {@link #initialize(MenuBuilder)} must be called for the + * menu to be functional. + * + * @hide + */ +public interface MenuView { + /** + * Initializes the menu to the given menu. This should be called after the + * view is inflated. + * + * @param menu The menu that this MenuView should display. + */ + public void initialize(MenuBuilder menu); + + /** + * Returns the default animations to be used for this menu when entering/exiting. + * @return A resource ID for the default animations to be used for this menu. + */ + public int getWindowAnimations(); + + /** + * Minimal interface for a menu item view. {@link #initialize(MenuItemImpl, int)} must be called + * for the item to be functional. + */ + public interface ItemView { + /** + * Initializes with the provided MenuItemData. This should be called after the view is + * inflated. + * @param itemData The item that this ItemView should display. + * @param menuType The type of this menu, one of + * {@link MenuBuilder#TYPE_ICON}, {@link MenuBuilder#TYPE_EXPANDED}, + * {@link MenuBuilder#TYPE_DIALOG}). + */ + public void initialize(MenuItemImpl itemData, int menuType); + + /** + * Gets the item data that this view is displaying. + * @return the item data, or null if there is not one + */ + public MenuItemImpl getItemData(); + + /** + * Sets the title of the item view. + * @param title The title to set. + */ + public void setTitle(CharSequence title); + + /** + * Sets the enabled state of the item view. + * @param enabled Whether the item view should be enabled. + */ + public void setEnabled(boolean enabled); + + /** + * Displays the checkbox for the item view. This does not ensure the item view will be + * checked, for that use {@link #setChecked}. + * @param checkable Whether to display the checkbox or to hide it + */ + public void setCheckable(boolean checkable); + + /** + * Checks the checkbox for the item view. If the checkbox is hidden, it will NOT be + * made visible, call {@link #setCheckable(boolean)} for that. + * @param checked Whether the checkbox should be checked + */ + public void setChecked(boolean checked); + + /** + * Sets the shortcut for the item. + * @param showShortcut Whether a shortcut should be shown(if false, the value of + * shortcutKey should be ignored). + * @param shortcutKey The shortcut key that should be shown on the ItemView. + */ + public void setShortcut(boolean showShortcut, char shortcutKey); + + /** + * Set the icon of this item view. + * @param icon The icon of this item. null to hide the icon. + */ + public void setIcon(Drawable icon); + + /** + * Whether this item view prefers displaying the condensed title rather + * than the normal title. If a condensed title is not available, the + * normal title will be used. + * + * @return Whether this item view prefers displaying the condensed + * title. + */ + public boolean prefersCondensedTitle(); + + /** + * Whether this item view shows an icon. + * + * @return Whether this item view shows an icon. + */ + public boolean showsIcon(); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java new file mode 100644 index 000000000..3d4dd42fd --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/MenuWrapper.java @@ -0,0 +1,185 @@ +package com.actionbarsherlock.internal.view.menu; + +import java.util.WeakHashMap; +import android.content.ComponentName; +import android.content.Intent; +import android.view.KeyEvent; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +public class MenuWrapper implements Menu { + private final android.view.Menu mNativeMenu; + + private final WeakHashMap mNativeMap = + new WeakHashMap(); + + + public MenuWrapper(android.view.Menu nativeMenu) { + mNativeMenu = nativeMenu; + } + + public android.view.Menu unwrap() { + return mNativeMenu; + } + + private MenuItem addInternal(android.view.MenuItem nativeItem) { + MenuItem item = new MenuItemWrapper(nativeItem); + mNativeMap.put(nativeItem, item); + return item; + } + + @Override + public MenuItem add(CharSequence title) { + return addInternal(mNativeMenu.add(title)); + } + + @Override + public MenuItem add(int titleRes) { + return addInternal(mNativeMenu.add(titleRes)); + } + + @Override + public MenuItem add(int groupId, int itemId, int order, CharSequence title) { + return addInternal(mNativeMenu.add(groupId, itemId, order, title)); + } + + @Override + public MenuItem add(int groupId, int itemId, int order, int titleRes) { + return addInternal(mNativeMenu.add(groupId, itemId, order, titleRes)); + } + + private SubMenu addInternal(android.view.SubMenu nativeSubMenu) { + SubMenu subMenu = new SubMenuWrapper(nativeSubMenu); + android.view.MenuItem nativeItem = nativeSubMenu.getItem(); + MenuItem item = subMenu.getItem(); + mNativeMap.put(nativeItem, item); + return subMenu; + } + + @Override + public SubMenu addSubMenu(CharSequence title) { + return addInternal(mNativeMenu.addSubMenu(title)); + } + + @Override + public SubMenu addSubMenu(int titleRes) { + return addInternal(mNativeMenu.addSubMenu(titleRes)); + } + + @Override + public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { + return addInternal(mNativeMenu.addSubMenu(groupId, itemId, order, title)); + } + + @Override + public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { + return addInternal(mNativeMenu.addSubMenu(groupId, itemId, order, titleRes)); + } + + @Override + public int addIntentOptions(int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { + int result; + if (outSpecificItems != null) { + android.view.MenuItem[] nativeOutItems = new android.view.MenuItem[outSpecificItems.length]; + result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, nativeOutItems); + for (int i = 0, length = outSpecificItems.length; i < length; i++) { + outSpecificItems[i] = new MenuItemWrapper(nativeOutItems[i]); + } + } else { + result = mNativeMenu.addIntentOptions(groupId, itemId, order, caller, specifics, intent, flags, null); + } + return result; + } + + @Override + public void removeItem(int id) { + mNativeMenu.removeItem(id); + } + + @Override + public void removeGroup(int groupId) { + mNativeMenu.removeGroup(groupId); + } + + @Override + public void clear() { + mNativeMap.clear(); + mNativeMenu.clear(); + } + + @Override + public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { + mNativeMenu.setGroupCheckable(group, checkable, exclusive); + } + + @Override + public void setGroupVisible(int group, boolean visible) { + mNativeMenu.setGroupVisible(group, visible); + } + + @Override + public void setGroupEnabled(int group, boolean enabled) { + mNativeMenu.setGroupEnabled(group, enabled); + } + + @Override + public boolean hasVisibleItems() { + return mNativeMenu.hasVisibleItems(); + } + + @Override + public MenuItem findItem(int id) { + android.view.MenuItem nativeItem = mNativeMenu.findItem(id); + return findItem(nativeItem); + } + + public MenuItem findItem(android.view.MenuItem nativeItem) { + if (nativeItem == null) { + return null; + } + + MenuItem wrapped = mNativeMap.get(nativeItem); + if (wrapped != null) { + return wrapped; + } + + return addInternal(nativeItem); + } + + @Override + public int size() { + return mNativeMenu.size(); + } + + @Override + public MenuItem getItem(int index) { + android.view.MenuItem nativeItem = mNativeMenu.getItem(index); + return findItem(nativeItem); + } + + @Override + public void close() { + mNativeMenu.close(); + } + + @Override + public boolean performShortcut(int keyCode, KeyEvent event, int flags) { + return mNativeMenu.performShortcut(keyCode, event, flags); + } + + @Override + public boolean isShortcutKey(int keyCode, KeyEvent event) { + return mNativeMenu.isShortcutKey(keyCode, event); + } + + @Override + public boolean performIdentifierAction(int id, int flags) { + return mNativeMenu.performIdentifierAction(id, flags); + } + + @Override + public void setQwertyMode(boolean isQwerty) { + mNativeMenu.setQwertyMode(isQwerty); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java new file mode 100644 index 000000000..6679cf386 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuBuilder.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.view.menu; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.View; + +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +/** + * The model for a sub menu, which is an extension of the menu. Most methods are proxied to + * the parent menu. + */ +public class SubMenuBuilder extends MenuBuilder implements SubMenu { + private MenuBuilder mParentMenu; + private MenuItemImpl mItem; + + public SubMenuBuilder(Context context, MenuBuilder parentMenu, MenuItemImpl item) { + super(context); + + mParentMenu = parentMenu; + mItem = item; + } + + @Override + public void setQwertyMode(boolean isQwerty) { + mParentMenu.setQwertyMode(isQwerty); + } + + @Override + public boolean isQwertyMode() { + return mParentMenu.isQwertyMode(); + } + + @Override + public void setShortcutsVisible(boolean shortcutsVisible) { + mParentMenu.setShortcutsVisible(shortcutsVisible); + } + + @Override + public boolean isShortcutsVisible() { + return mParentMenu.isShortcutsVisible(); + } + + public Menu getParentMenu() { + return mParentMenu; + } + + public MenuItem getItem() { + return mItem; + } + + @Override + public void setCallback(Callback callback) { + mParentMenu.setCallback(callback); + } + + @Override + public MenuBuilder getRootMenu() { + return mParentMenu; + } + + @Override + boolean dispatchMenuItemSelected(MenuBuilder menu, MenuItem item) { + return super.dispatchMenuItemSelected(menu, item) || + mParentMenu.dispatchMenuItemSelected(menu, item); + } + + public SubMenu setIcon(Drawable icon) { + mItem.setIcon(icon); + return this; + } + + public SubMenu setIcon(int iconRes) { + mItem.setIcon(iconRes); + return this; + } + + public SubMenu setHeaderIcon(Drawable icon) { + return (SubMenu) super.setHeaderIconInt(icon); + } + + public SubMenu setHeaderIcon(int iconRes) { + return (SubMenu) super.setHeaderIconInt(iconRes); + } + + public SubMenu setHeaderTitle(CharSequence title) { + return (SubMenu) super.setHeaderTitleInt(title); + } + + public SubMenu setHeaderTitle(int titleRes) { + return (SubMenu) super.setHeaderTitleInt(titleRes); + } + + public SubMenu setHeaderView(View view) { + return (SubMenu) super.setHeaderViewInt(view); + } + + @Override + public boolean expandItemActionView(MenuItemImpl item) { + return mParentMenu.expandItemActionView(item); + } + + @Override + public boolean collapseItemActionView(MenuItemImpl item) { + return mParentMenu.collapseItemActionView(item); + } + + @Override + public String getActionViewStatesKey() { + final int itemId = mItem != null ? mItem.getItemId() : 0; + if (itemId == 0) { + return null; + } + return super.getActionViewStatesKey() + ":" + itemId; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java new file mode 100644 index 000000000..7d307acb1 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/SubMenuWrapper.java @@ -0,0 +1,72 @@ +package com.actionbarsherlock.internal.view.menu; + +import android.graphics.drawable.Drawable; +import android.view.View; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.SubMenu; + +public class SubMenuWrapper extends MenuWrapper implements SubMenu { + private final android.view.SubMenu mNativeSubMenu; + private MenuItem mItem = null; + + public SubMenuWrapper(android.view.SubMenu nativeSubMenu) { + super(nativeSubMenu); + mNativeSubMenu = nativeSubMenu; + } + + + @Override + public SubMenu setHeaderTitle(int titleRes) { + mNativeSubMenu.setHeaderTitle(titleRes); + return this; + } + + @Override + public SubMenu setHeaderTitle(CharSequence title) { + mNativeSubMenu.setHeaderTitle(title); + return this; + } + + @Override + public SubMenu setHeaderIcon(int iconRes) { + mNativeSubMenu.setHeaderIcon(iconRes); + return this; + } + + @Override + public SubMenu setHeaderIcon(Drawable icon) { + mNativeSubMenu.setHeaderIcon(icon); + return this; + } + + @Override + public SubMenu setHeaderView(View view) { + mNativeSubMenu.setHeaderView(view); + return this; + } + + @Override + public void clearHeader() { + mNativeSubMenu.clearHeader(); + } + + @Override + public SubMenu setIcon(int iconRes) { + mNativeSubMenu.setIcon(iconRes); + return this; + } + + @Override + public SubMenu setIcon(Drawable icon) { + mNativeSubMenu.setIcon(icon); + return this; + } + + @Override + public MenuItem getItem() { + if (mItem == null) { + mItem = new MenuItemWrapper(mNativeSubMenu.getItem()); + } + return mItem; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java new file mode 100644 index 000000000..3a4a44675 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/AbsActionBarView.java @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.os.Build; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; +import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; +import com.actionbarsherlock.internal.nineoldandroids.view.NineViewGroup; +import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; +import com.actionbarsherlock.internal.view.menu.ActionMenuView; + +import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; + +public abstract class AbsActionBarView extends NineViewGroup { + protected ActionMenuView mMenuView; + protected ActionMenuPresenter mActionMenuPresenter; + protected ActionBarContainer mSplitView; + protected boolean mSplitActionBar; + protected boolean mSplitWhenNarrow; + protected int mContentHeight; + + final Context mContext; + + protected Animator mVisibilityAnim; + protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); + + private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator(); + + private static final int FADE_DURATION = 200; + + public AbsActionBarView(Context context) { + super(context); + mContext = context; + } + + public AbsActionBarView(Context context, AttributeSet attrs) { + super(context, attrs); + mContext = context; + } + + public AbsActionBarView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mContext = context; + } + + /* + * Must be public so we can dispatch pre-2.2 via ActionBarImpl. + */ + @Override + public void onConfigurationChanged(Configuration newConfig) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { + super.onConfigurationChanged(newConfig); + } else if (mMenuView != null) { + mMenuView.onConfigurationChanged(newConfig); + } + + // Action bar can change size on configuration changes. + // Reread the desired height from the theme-specified style. + TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, + R.attr.actionBarStyle, 0); + setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); + a.recycle(); + if (mSplitWhenNarrow) { + setSplitActionBar(getResources_getBoolean(getContext(), + R.bool.abs__split_action_bar_is_narrow)); + } + if (mActionMenuPresenter != null) { + mActionMenuPresenter.onConfigurationChanged(newConfig); + } + } + + /** + * Sets whether the bar should be split right now, no questions asked. + * @param split true if the bar should split + */ + public void setSplitActionBar(boolean split) { + mSplitActionBar = split; + } + + /** + * Sets whether the bar should split if we enter a narrow screen configuration. + * @param splitWhenNarrow true if the bar should check to split after a config change + */ + public void setSplitWhenNarrow(boolean splitWhenNarrow) { + mSplitWhenNarrow = splitWhenNarrow; + } + + public void setContentHeight(int height) { + mContentHeight = height; + requestLayout(); + } + + public int getContentHeight() { + return mContentHeight; + } + + public void setSplitView(ActionBarContainer splitView) { + mSplitView = splitView; + } + + /** + * @return Current visibility or if animating, the visibility being animated to. + */ + public int getAnimatedVisibility() { + if (mVisibilityAnim != null) { + return mVisAnimListener.mFinalVisibility; + } + return getVisibility(); + } + + public void animateToVisibility(int visibility) { + if (mVisibilityAnim != null) { + mVisibilityAnim.cancel(); + } + if (visibility == VISIBLE) { + if (getVisibility() != VISIBLE) { + setAlpha(0); + if (mSplitView != null && mMenuView != null) { + mMenuView.setAlpha(0); + } + } + ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); + anim.setDuration(FADE_DURATION); + anim.setInterpolator(sAlphaInterpolator); + if (mSplitView != null && mMenuView != null) { + AnimatorSet set = new AnimatorSet(); + ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1); + splitAnim.setDuration(FADE_DURATION); + set.addListener(mVisAnimListener.withFinalVisibility(visibility)); + set.play(anim).with(splitAnim); + set.start(); + } else { + anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); + anim.start(); + } + } else { + ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); + anim.setDuration(FADE_DURATION); + anim.setInterpolator(sAlphaInterpolator); + if (mSplitView != null && mMenuView != null) { + AnimatorSet set = new AnimatorSet(); + ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0); + splitAnim.setDuration(FADE_DURATION); + set.addListener(mVisAnimListener.withFinalVisibility(visibility)); + set.play(anim).with(splitAnim); + set.start(); + } else { + anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); + anim.start(); + } + } + } + + @Override + public void setVisibility(int visibility) { + if (mVisibilityAnim != null) { + mVisibilityAnim.end(); + } + super.setVisibility(visibility); + } + + public boolean showOverflowMenu() { + if (mActionMenuPresenter != null) { + return mActionMenuPresenter.showOverflowMenu(); + } + return false; + } + + public void postShowOverflowMenu() { + post(new Runnable() { + public void run() { + showOverflowMenu(); + } + }); + } + + public boolean hideOverflowMenu() { + if (mActionMenuPresenter != null) { + return mActionMenuPresenter.hideOverflowMenu(); + } + return false; + } + + public boolean isOverflowMenuShowing() { + if (mActionMenuPresenter != null) { + return mActionMenuPresenter.isOverflowMenuShowing(); + } + return false; + } + + public boolean isOverflowReserved() { + return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved(); + } + + public void dismissPopupMenus() { + if (mActionMenuPresenter != null) { + mActionMenuPresenter.dismissPopupMenus(); + } + } + + protected int measureChildView(View child, int availableWidth, int childSpecHeight, + int spacing) { + child.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), + childSpecHeight); + + availableWidth -= child.getMeasuredWidth(); + availableWidth -= spacing; + + return Math.max(0, availableWidth); + } + + protected int positionChild(View child, int x, int y, int contentHeight) { + int childWidth = child.getMeasuredWidth(); + int childHeight = child.getMeasuredHeight(); + int childTop = y + (contentHeight - childHeight) / 2; + + child.layout(x, childTop, x + childWidth, childTop + childHeight); + + return childWidth; + } + + protected int positionChildInverse(View child, int x, int y, int contentHeight) { + int childWidth = child.getMeasuredWidth(); + int childHeight = child.getMeasuredHeight(); + int childTop = y + (contentHeight - childHeight) / 2; + + child.layout(x - childWidth, childTop, x, childTop + childHeight); + + return childWidth; + } + + protected class VisibilityAnimListener implements Animator.AnimatorListener { + private boolean mCanceled = false; + int mFinalVisibility; + + public VisibilityAnimListener withFinalVisibility(int visibility) { + mFinalVisibility = visibility; + return this; + } + + @Override + public void onAnimationStart(Animator animation) { + setVisibility(VISIBLE); + mVisibilityAnim = animation; + mCanceled = false; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCanceled) return; + + mVisibilityAnim = null; + setVisibility(mFinalVisibility); + if (mSplitView != null && mMenuView != null) { + mMenuView.setVisibility(mFinalVisibility); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + mCanceled = true; + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java new file mode 100644 index 000000000..1d9c68b37 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContainer.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout; + +/** + * This class acts as a container for the action bar view and action mode context views. + * It applies special styles as needed to help handle animated transitions between them. + * @hide + */ +public class ActionBarContainer extends NineFrameLayout { + private boolean mIsTransitioning; + private View mTabContainer; + private ActionBarView mActionBarView; + + private Drawable mBackground; + private Drawable mStackedBackground; + private Drawable mSplitBackground; + private boolean mIsSplit; + private boolean mIsStacked; + + public ActionBarContainer(Context context) { + this(context, null); + } + + public ActionBarContainer(Context context, AttributeSet attrs) { + super(context, attrs); + + setBackgroundDrawable(null); + + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.SherlockActionBar); + mBackground = a.getDrawable(R.styleable.SherlockActionBar_background); + mStackedBackground = a.getDrawable( + R.styleable.SherlockActionBar_backgroundStacked); + + //Fix for issue #379 + if (mStackedBackground instanceof ColorDrawable && Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(bitmap); + mStackedBackground.draw(c); + int color = bitmap.getPixel(0, 0); + bitmap.recycle(); + mStackedBackground = new IcsColorDrawable(color); + } + + if (getId() == R.id.abs__split_action_bar) { + mIsSplit = true; + mSplitBackground = a.getDrawable( + R.styleable.SherlockActionBar_backgroundSplit); + } + a.recycle(); + + setWillNotDraw(mIsSplit ? mSplitBackground == null : + mBackground == null && mStackedBackground == null); + } + + @Override + public void onFinishInflate() { + super.onFinishInflate(); + mActionBarView = (ActionBarView) findViewById(R.id.abs__action_bar); + } + + public void setPrimaryBackground(Drawable bg) { + mBackground = bg; + invalidate(); + } + + public void setStackedBackground(Drawable bg) { + mStackedBackground = bg; + invalidate(); + } + + public void setSplitBackground(Drawable bg) { + mSplitBackground = bg; + invalidate(); + } + + /** + * Set the action bar into a "transitioning" state. While transitioning + * the bar will block focus and touch from all of its descendants. This + * prevents the user from interacting with the bar while it is animating + * in or out. + * + * @param isTransitioning true if the bar is currently transitioning, false otherwise. + */ + public void setTransitioning(boolean isTransitioning) { + mIsTransitioning = isTransitioning; + setDescendantFocusability(isTransitioning ? FOCUS_BLOCK_DESCENDANTS + : FOCUS_AFTER_DESCENDANTS); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return mIsTransitioning || super.onInterceptTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + super.onTouchEvent(ev); + + // An action bar always eats touch events. + return true; + } + + @Override + public boolean onHoverEvent(MotionEvent ev) { + super.onHoverEvent(ev); + + // An action bar always eats hover events. + return true; + } + + public void setTabContainer(ScrollingTabContainerView tabView) { + if (mTabContainer != null) { + removeView(mTabContainer); + } + mTabContainer = tabView; + if (tabView != null) { + addView(tabView); + final ViewGroup.LayoutParams lp = tabView.getLayoutParams(); + lp.width = LayoutParams.MATCH_PARENT; + lp.height = LayoutParams.WRAP_CONTENT; + tabView.setAllowCollapse(false); + } + } + + public View getTabContainer() { + return mTabContainer; + } + + @Override + public void onDraw(Canvas canvas) { + if (getWidth() == 0 || getHeight() == 0) { + return; + } + + if (mIsSplit) { + if (mSplitBackground != null) mSplitBackground.draw(canvas); + } else { + if (mBackground != null) { + mBackground.draw(canvas); + } + if (mStackedBackground != null && mIsStacked) { + mStackedBackground.draw(canvas); + } + } + } + + //This causes the animation reflection to fail on pre-HC platforms + //@Override + //public android.view.ActionMode startActionModeForChild(View child, android.view.ActionMode.Callback callback) { + // // No starting an action mode for an action bar child! (Where would it go?) + // return null; + //} + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + if (mActionBarView == null) return; + + final LayoutParams lp = (LayoutParams) mActionBarView.getLayoutParams(); + final int actionBarViewHeight = mActionBarView.isCollapsed() ? 0 : + mActionBarView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; + + if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { + final int mode = MeasureSpec.getMode(heightMeasureSpec); + if (mode == MeasureSpec.AT_MOST) { + final int maxHeight = MeasureSpec.getSize(heightMeasureSpec); + setMeasuredDimension(getMeasuredWidth(), + Math.min(actionBarViewHeight + mTabContainer.getMeasuredHeight(), + maxHeight)); + } + } + } + + @Override + public void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + + final boolean hasTabs = mTabContainer != null && mTabContainer.getVisibility() != GONE; + + if (mTabContainer != null && mTabContainer.getVisibility() != GONE) { + final int containerHeight = getMeasuredHeight(); + final int tabHeight = mTabContainer.getMeasuredHeight(); + + if ((mActionBarView.getDisplayOptions() & ActionBar.DISPLAY_SHOW_HOME) == 0) { + // Not showing home, put tabs on top. + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + + if (child == mTabContainer) continue; + + if (!mActionBarView.isCollapsed()) { + child.offsetTopAndBottom(tabHeight); + } + } + mTabContainer.layout(l, 0, r, tabHeight); + } else { + mTabContainer.layout(l, containerHeight - tabHeight, r, containerHeight); + } + } + + boolean needsInvalidate = false; + if (mIsSplit) { + if (mSplitBackground != null) { + mSplitBackground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + needsInvalidate = true; + } + } else { + if (mBackground != null) { + mBackground.setBounds(mActionBarView.getLeft(), mActionBarView.getTop(), + mActionBarView.getRight(), mActionBarView.getBottom()); + needsInvalidate = true; + } + if ((mIsStacked = hasTabs && mStackedBackground != null)) { + mStackedBackground.setBounds(mTabContainer.getLeft(), mTabContainer.getTop(), + mTabContainer.getRight(), mTabContainer.getBottom()); + needsInvalidate = true; + } + } + + if (needsInvalidate) { + invalidate(); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java new file mode 100644 index 000000000..9ec250f38 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarContextView.java @@ -0,0 +1,518 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.view.animation.DecelerateInterpolator; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator.AnimatorListener; +import com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet; +import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; +import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy; +import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout; +import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; +import com.actionbarsherlock.internal.view.menu.ActionMenuView; +import com.actionbarsherlock.internal.view.menu.MenuBuilder; +import com.actionbarsherlock.view.ActionMode; + +/** + * @hide + */ +public class ActionBarContextView extends AbsActionBarView implements AnimatorListener { + //UNUSED private static final String TAG = "ActionBarContextView"; + + private CharSequence mTitle; + private CharSequence mSubtitle; + + private NineLinearLayout mClose; + private View mCustomView; + private LinearLayout mTitleLayout; + private TextView mTitleView; + private TextView mSubtitleView; + private int mTitleStyleRes; + private int mSubtitleStyleRes; + private Drawable mSplitBackground; + + private Animator mCurrentAnimation; + private boolean mAnimateInOnLayout; + private int mAnimationMode; + + private static final int ANIMATE_IDLE = 0; + private static final int ANIMATE_IN = 1; + private static final int ANIMATE_OUT = 2; + + public ActionBarContextView(Context context) { + this(context, null); + } + + public ActionBarContextView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.actionModeStyle); + } + + public ActionBarContextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockActionMode, defStyle, 0); + setBackgroundDrawable(a.getDrawable( + R.styleable.SherlockActionMode_background)); + mTitleStyleRes = a.getResourceId( + R.styleable.SherlockActionMode_titleTextStyle, 0); + mSubtitleStyleRes = a.getResourceId( + R.styleable.SherlockActionMode_subtitleTextStyle, 0); + + mContentHeight = a.getLayoutDimension( + R.styleable.SherlockActionMode_height, 0); + + mSplitBackground = a.getDrawable( + R.styleable.SherlockActionMode_backgroundSplit); + + a.recycle(); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mActionMenuPresenter != null) { + mActionMenuPresenter.hideOverflowMenu(); + mActionMenuPresenter.hideSubMenus(); + } + } + + @Override + public void setSplitActionBar(boolean split) { + if (mSplitActionBar != split) { + if (mActionMenuPresenter != null) { + // Mode is already active; move everything over and adjust the menu itself. + final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT); + if (!split) { + mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + mMenuView.setBackgroundDrawable(null); + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) oldParent.removeView(mMenuView); + addView(mMenuView, layoutParams); + } else { + // Allow full screen width in split mode. + mActionMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels, true); + // No limit to the item count; use whatever will fit. + mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); + // Span the whole width + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = mContentHeight; + mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + mMenuView.setBackgroundDrawable(mSplitBackground); + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) oldParent.removeView(mMenuView); + mSplitView.addView(mMenuView, layoutParams); + } + } + super.setSplitActionBar(split); + } + } + + public void setContentHeight(int height) { + mContentHeight = height; + } + + public void setCustomView(View view) { + if (mCustomView != null) { + removeView(mCustomView); + } + mCustomView = view; + if (mTitleLayout != null) { + removeView(mTitleLayout); + mTitleLayout = null; + } + if (view != null) { + addView(view); + } + requestLayout(); + } + + public void setTitle(CharSequence title) { + mTitle = title; + initTitle(); + } + + public void setSubtitle(CharSequence subtitle) { + mSubtitle = subtitle; + initTitle(); + } + + public CharSequence getTitle() { + return mTitle; + } + + public CharSequence getSubtitle() { + return mSubtitle; + } + + private void initTitle() { + if (mTitleLayout == null) { + LayoutInflater inflater = LayoutInflater.from(getContext()); + inflater.inflate(R.layout.abs__action_bar_title_item, this); + mTitleLayout = (LinearLayout) getChildAt(getChildCount() - 1); + mTitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_title); + mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_subtitle); + if (mTitleStyleRes != 0) { + mTitleView.setTextAppearance(mContext, mTitleStyleRes); + } + if (mSubtitleStyleRes != 0) { + mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); + } + } + + mTitleView.setText(mTitle); + mSubtitleView.setText(mSubtitle); + + final boolean hasTitle = !TextUtils.isEmpty(mTitle); + final boolean hasSubtitle = !TextUtils.isEmpty(mSubtitle); + mSubtitleView.setVisibility(hasSubtitle ? VISIBLE : GONE); + mTitleLayout.setVisibility(hasTitle || hasSubtitle ? VISIBLE : GONE); + if (mTitleLayout.getParent() == null) { + addView(mTitleLayout); + } + } + + public void initForMode(final ActionMode mode) { + if (mClose == null) { + LayoutInflater inflater = LayoutInflater.from(mContext); + mClose = (NineLinearLayout)inflater.inflate(R.layout.abs__action_mode_close_item, this, false); + addView(mClose); + } else if (mClose.getParent() == null) { + addView(mClose); + } + + View closeButton = mClose.findViewById(R.id.abs__action_mode_close_button); + closeButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mode.finish(); + } + }); + + final MenuBuilder menu = (MenuBuilder) mode.getMenu(); + if (mActionMenuPresenter != null) { + mActionMenuPresenter.dismissPopupMenus(); + } + mActionMenuPresenter = new ActionMenuPresenter(mContext); + mActionMenuPresenter.setReserveOverflow(true); + + final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT); + if (!mSplitActionBar) { + menu.addMenuPresenter(mActionMenuPresenter); + mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + mMenuView.setBackgroundDrawable(null); + addView(mMenuView, layoutParams); + } else { + // Allow full screen width in split mode. + mActionMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels, true); + // No limit to the item count; use whatever will fit. + mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); + // Span the whole width + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = mContentHeight; + menu.addMenuPresenter(mActionMenuPresenter); + mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + mMenuView.setBackgroundDrawable(mSplitBackground); + mSplitView.addView(mMenuView, layoutParams); + } + + mAnimateInOnLayout = true; + } + + public void closeMode() { + if (mAnimationMode == ANIMATE_OUT) { + // Called again during close; just finish what we were doing. + return; + } + if (mClose == null) { + killMode(); + return; + } + + finishAnimation(); + mAnimationMode = ANIMATE_OUT; + mCurrentAnimation = makeOutAnimation(); + mCurrentAnimation.start(); + } + + private void finishAnimation() { + final Animator a = mCurrentAnimation; + if (a != null) { + mCurrentAnimation = null; + a.end(); + } + } + + public void killMode() { + finishAnimation(); + removeAllViews(); + if (mSplitView != null) { + mSplitView.removeView(mMenuView); + } + mCustomView = null; + mMenuView = null; + mAnimateInOnLayout = false; + } + + @Override + public boolean showOverflowMenu() { + if (mActionMenuPresenter != null) { + return mActionMenuPresenter.showOverflowMenu(); + } + return false; + } + + @Override + public boolean hideOverflowMenu() { + if (mActionMenuPresenter != null) { + return mActionMenuPresenter.hideOverflowMenu(); + } + return false; + } + + @Override + public boolean isOverflowMenuShowing() { + if (mActionMenuPresenter != null) { + return mActionMenuPresenter.isOverflowMenuShowing(); + } + return false; + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + // Used by custom views if they don't supply layout params. Everything else + // added to an ActionBarContextView should have them already. + return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new MarginLayoutParams(getContext(), attrs); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + if (widthMode != MeasureSpec.EXACTLY) { + throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + + "with android:layout_width=\"match_parent\" (or fill_parent)"); + } + + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + if (heightMode == MeasureSpec.UNSPECIFIED) { + throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + + "with android:layout_height=\"wrap_content\""); + } + + final int contentWidth = MeasureSpec.getSize(widthMeasureSpec); + + int maxHeight = mContentHeight > 0 ? + mContentHeight : MeasureSpec.getSize(heightMeasureSpec); + + final int verticalPadding = getPaddingTop() + getPaddingBottom(); + int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight(); + final int height = maxHeight - verticalPadding; + final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); + + if (mClose != null) { + availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0); + MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams(); + availableWidth -= lp.leftMargin + lp.rightMargin; + } + + if (mMenuView != null && mMenuView.getParent() == this) { + availableWidth = measureChildView(mMenuView, availableWidth, + childSpecHeight, 0); + } + + if (mTitleLayout != null && mCustomView == null) { + availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0); + } + + if (mCustomView != null) { + ViewGroup.LayoutParams lp = mCustomView.getLayoutParams(); + final int customWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? + MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; + final int customWidth = lp.width >= 0 ? + Math.min(lp.width, availableWidth) : availableWidth; + final int customHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? + MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; + final int customHeight = lp.height >= 0 ? + Math.min(lp.height, height) : height; + mCustomView.measure(MeasureSpec.makeMeasureSpec(customWidth, customWidthMode), + MeasureSpec.makeMeasureSpec(customHeight, customHeightMode)); + } + + if (mContentHeight <= 0) { + int measuredHeight = 0; + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + View v = getChildAt(i); + int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; + if (paddedViewHeight > measuredHeight) { + measuredHeight = paddedViewHeight; + } + } + setMeasuredDimension(contentWidth, measuredHeight); + } else { + setMeasuredDimension(contentWidth, maxHeight); + } + } + + private Animator makeInAnimation() { + mClose.setTranslationX(-mClose.getWidth() - + ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin); + ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", 0); + buttonAnimator.setDuration(200); + buttonAnimator.addListener(this); + buttonAnimator.setInterpolator(new DecelerateInterpolator()); + + AnimatorSet set = new AnimatorSet(); + AnimatorSet.Builder b = set.play(buttonAnimator); + + if (mMenuView != null) { + final int count = mMenuView.getChildCount(); + if (count > 0) { + for (int i = count - 1, j = 0; i >= 0; i--, j++) { + AnimatorProxy child = AnimatorProxy.wrap(mMenuView.getChildAt(i)); + child.setScaleY(0); + ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0, 1); + a.setDuration(100); + a.setStartDelay(j * 70); + b.with(a); + } + } + } + + return set; + } + + private Animator makeOutAnimation() { + ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", + -mClose.getWidth() - ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin); + buttonAnimator.setDuration(200); + buttonAnimator.addListener(this); + buttonAnimator.setInterpolator(new DecelerateInterpolator()); + + AnimatorSet set = new AnimatorSet(); + AnimatorSet.Builder b = set.play(buttonAnimator); + + if (mMenuView != null) { + final int count = mMenuView.getChildCount(); + if (count > 0) { + for (int i = 0; i < 0; i++) { + AnimatorProxy child = AnimatorProxy.wrap(mMenuView.getChildAt(i)); + child.setScaleY(0); + ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0); + a.setDuration(100); + a.setStartDelay(i * 70); + b.with(a); + } + } + } + + return set; + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int x = getPaddingLeft(); + final int y = getPaddingTop(); + final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); + + if (mClose != null && mClose.getVisibility() != GONE) { + MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams(); + x += lp.leftMargin; + x += positionChild(mClose, x, y, contentHeight); + x += lp.rightMargin; + + if (mAnimateInOnLayout) { + mAnimationMode = ANIMATE_IN; + mCurrentAnimation = makeInAnimation(); + mCurrentAnimation.start(); + mAnimateInOnLayout = false; + } + } + + if (mTitleLayout != null && mCustomView == null) { + x += positionChild(mTitleLayout, x, y, contentHeight); + } + + if (mCustomView != null) { + x += positionChild(mCustomView, x, y, contentHeight); + } + + x = r - l - getPaddingRight(); + + if (mMenuView != null) { + x -= positionChildInverse(mMenuView, x, y, contentHeight); + } + } + + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mAnimationMode == ANIMATE_OUT) { + killMode(); + } + mAnimationMode = ANIMATE_IDLE; + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { + // Action mode started + //TODO event.setSource(this); + event.setClassName(getClass().getName()); + event.setPackageName(getContext().getPackageName()); + event.setContentDescription(mTitle); + } else { + //TODO super.onInitializeAccessibilityEvent(event); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java new file mode 100644 index 000000000..4636de17f --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ActionBarView.java @@ -0,0 +1,1548 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.widget; + +import org.xmlpull.v1.XmlPullParser; +import android.app.Activity; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.accessibility.AccessibilityEvent; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.SpinnerAdapter; +import android.widget.TextView; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.ActionBar.OnNavigationListener; +import com.actionbarsherlock.internal.ActionBarSherlockCompat; +import com.actionbarsherlock.internal.view.menu.ActionMenuItem; +import com.actionbarsherlock.internal.view.menu.ActionMenuPresenter; +import com.actionbarsherlock.internal.view.menu.ActionMenuView; +import com.actionbarsherlock.internal.view.menu.MenuBuilder; +import com.actionbarsherlock.internal.view.menu.MenuItemImpl; +import com.actionbarsherlock.internal.view.menu.MenuPresenter; +import com.actionbarsherlock.internal.view.menu.MenuView; +import com.actionbarsherlock.internal.view.menu.SubMenuBuilder; +import com.actionbarsherlock.view.CollapsibleActionView; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.Window; + +import static com.actionbarsherlock.internal.ResourcesCompat.getResources_getBoolean; + +/** + * @hide + */ +public class ActionBarView extends AbsActionBarView { + private static final String TAG = "ActionBarView"; + private static final boolean DEBUG = false; + + /** + * Display options applied by default + */ + public static final int DISPLAY_DEFAULT = 0; + + /** + * Display options that require re-layout as opposed to a simple invalidate + */ + private static final int DISPLAY_RELAYOUT_MASK = + ActionBar.DISPLAY_SHOW_HOME | + ActionBar.DISPLAY_USE_LOGO | + ActionBar.DISPLAY_HOME_AS_UP | + ActionBar.DISPLAY_SHOW_CUSTOM | + ActionBar.DISPLAY_SHOW_TITLE; + + private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.LEFT | Gravity.CENTER_VERTICAL; + + private int mNavigationMode; + private int mDisplayOptions = -1; + private CharSequence mTitle; + private CharSequence mSubtitle; + private Drawable mIcon; + private Drawable mLogo; + + private HomeView mHomeLayout; + private HomeView mExpandedHomeLayout; + private LinearLayout mTitleLayout; + private TextView mTitleView; + private TextView mSubtitleView; + private View mTitleUpView; + + private IcsSpinner mSpinner; + private IcsLinearLayout mListNavLayout; + private ScrollingTabContainerView mTabScrollView; + private View mCustomNavView; + private IcsProgressBar mProgressView; + private IcsProgressBar mIndeterminateProgressView; + + private int mProgressBarPadding; + private int mItemPadding; + + private int mTitleStyleRes; + private int mSubtitleStyleRes; + private int mProgressStyle; + private int mIndeterminateProgressStyle; + + private boolean mUserTitle; + private boolean mIncludeTabs; + private boolean mIsCollapsable; + private boolean mIsCollapsed; + + private MenuBuilder mOptionsMenu; + + private ActionBarContextView mContextView; + + private ActionMenuItem mLogoNavItem; + + private SpinnerAdapter mSpinnerAdapter; + private OnNavigationListener mCallback; + + //UNUSED private Runnable mTabSelector; + + private ExpandedActionViewMenuPresenter mExpandedMenuPresenter; + View mExpandedActionView; + + Window.Callback mWindowCallback; + + @SuppressWarnings("rawtypes") + private final IcsAdapterView.OnItemSelectedListener mNavItemSelectedListener = + new IcsAdapterView.OnItemSelectedListener() { + public void onItemSelected(IcsAdapterView parent, View view, int position, long id) { + if (mCallback != null) { + mCallback.onNavigationItemSelected(position, id); + } + } + public void onNothingSelected(IcsAdapterView parent) { + // Do nothing + } + }; + + private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() { + @Override + public void onClick(View v) { + final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem; + if (item != null) { + item.collapseActionView(); + } + } + }; + + private final OnClickListener mUpClickListener = new OnClickListener() { + public void onClick(View v) { + mWindowCallback.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, mLogoNavItem); + } + }; + + public ActionBarView(Context context, AttributeSet attrs) { + super(context, attrs); + + // Background is always provided by the container. + setBackgroundResource(0); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockActionBar, + R.attr.actionBarStyle, 0); + + ApplicationInfo appInfo = context.getApplicationInfo(); + PackageManager pm = context.getPackageManager(); + mNavigationMode = a.getInt(R.styleable.SherlockActionBar_navigationMode, + ActionBar.NAVIGATION_MODE_STANDARD); + mTitle = a.getText(R.styleable.SherlockActionBar_title); + mSubtitle = a.getText(R.styleable.SherlockActionBar_subtitle); + + mLogo = a.getDrawable(R.styleable.SherlockActionBar_logo); + if (mLogo == null) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + if (context instanceof Activity) { + //Even though native methods existed in API 9 and 10 they don't work + //so just parse the manifest to look for the logo pre-Honeycomb + final int resId = loadLogoFromManifest((Activity) context); + if (resId != 0) { + mLogo = context.getResources().getDrawable(resId); + } + } + } else { + if (context instanceof Activity) { + try { + mLogo = pm.getActivityLogo(((Activity) context).getComponentName()); + } catch (NameNotFoundException e) { + Log.e(TAG, "Activity component name not found!", e); + } + } + if (mLogo == null) { + mLogo = appInfo.loadLogo(pm); + } + } + } + + mIcon = a.getDrawable(R.styleable.SherlockActionBar_icon); + if (mIcon == null) { + if (context instanceof Activity) { + try { + mIcon = pm.getActivityIcon(((Activity) context).getComponentName()); + } catch (NameNotFoundException e) { + Log.e(TAG, "Activity component name not found!", e); + } + } + if (mIcon == null) { + mIcon = appInfo.loadIcon(pm); + } + } + + final LayoutInflater inflater = LayoutInflater.from(context); + + final int homeResId = a.getResourceId( + R.styleable.SherlockActionBar_homeLayout, + R.layout.abs__action_bar_home); + + mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false); + + mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false); + mExpandedHomeLayout.setUp(true); + mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener); + mExpandedHomeLayout.setContentDescription(getResources().getText( + R.string.abs__action_bar_up_description)); + + mTitleStyleRes = a.getResourceId(R.styleable.SherlockActionBar_titleTextStyle, 0); + mSubtitleStyleRes = a.getResourceId(R.styleable.SherlockActionBar_subtitleTextStyle, 0); + mProgressStyle = a.getResourceId(R.styleable.SherlockActionBar_progressBarStyle, 0); + mIndeterminateProgressStyle = a.getResourceId( + R.styleable.SherlockActionBar_indeterminateProgressStyle, 0); + + mProgressBarPadding = a.getDimensionPixelOffset(R.styleable.SherlockActionBar_progressBarPadding, 0); + mItemPadding = a.getDimensionPixelOffset(R.styleable.SherlockActionBar_itemPadding, 0); + + setDisplayOptions(a.getInt(R.styleable.SherlockActionBar_displayOptions, DISPLAY_DEFAULT)); + + final int customNavId = a.getResourceId(R.styleable.SherlockActionBar_customNavigationLayout, 0); + if (customNavId != 0) { + mCustomNavView = inflater.inflate(customNavId, this, false); + mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD; + setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM); + } + + mContentHeight = a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0); + + a.recycle(); + + mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle); + mHomeLayout.setOnClickListener(mUpClickListener); + mHomeLayout.setClickable(true); + mHomeLayout.setFocusable(true); + } + + /** + * Attempt to programmatically load the logo from the manifest file of an + * activity by using an XML pull parser. This should allow us to read the + * logo attribute regardless of the platform it is being run on. + * + * @param activity Activity instance. + * @return Logo resource ID. + */ + private static int loadLogoFromManifest(Activity activity) { + int logo = 0; + try { + final String thisPackage = activity.getClass().getName(); + if (DEBUG) Log.i(TAG, "Parsing AndroidManifest.xml for " + thisPackage); + + final String packageName = activity.getApplicationInfo().packageName; + final AssetManager am = activity.createPackageContext(packageName, 0).getAssets(); + final XmlResourceParser xml = am.openXmlResourceParser("AndroidManifest.xml"); + + int eventType = xml.getEventType(); + while (eventType != XmlPullParser.END_DOCUMENT) { + if (eventType == XmlPullParser.START_TAG) { + String name = xml.getName(); + + if ("application".equals(name)) { + //Check if the has the attribute + if (DEBUG) Log.d(TAG, "Got "); + + for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { + if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); + + if ("logo".equals(xml.getAttributeName(i))) { + logo = xml.getAttributeResourceValue(i, 0); + break; //out of for loop + } + } + } else if ("activity".equals(name)) { + //Check if the is us and has the attribute + if (DEBUG) Log.d(TAG, "Got "); + Integer activityLogo = null; + String activityPackage = null; + boolean isOurActivity = false; + + for (int i = xml.getAttributeCount() - 1; i >= 0; i--) { + if (DEBUG) Log.d(TAG, xml.getAttributeName(i) + ": " + xml.getAttributeValue(i)); + + //We need both uiOptions and name attributes + String attrName = xml.getAttributeName(i); + if ("logo".equals(attrName)) { + activityLogo = xml.getAttributeResourceValue(i, 0); + } else if ("name".equals(attrName)) { + activityPackage = ActionBarSherlockCompat.cleanActivityName(packageName, xml.getAttributeValue(i)); + if (!thisPackage.equals(activityPackage)) { + break; //on to the next + } + isOurActivity = true; + } + + //Make sure we have both attributes before processing + if ((activityLogo != null) && (activityPackage != null)) { + //Our activity, logo specified, override with our value + logo = activityLogo.intValue(); + } + } + if (isOurActivity) { + //If we matched our activity but it had no logo don't + //do any more processing of the manifest + break; + } + } + } + eventType = xml.nextToken(); + } + } catch (Exception e) { + e.printStackTrace(); + } + if (DEBUG) Log.i(TAG, "Returning " + Integer.toHexString(logo)); + return logo; + } + + /* + * Must be public so we can dispatch pre-2.2 via ActionBarImpl. + */ + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + mTitleView = null; + mSubtitleView = null; + mTitleUpView = null; + if (mTitleLayout != null && mTitleLayout.getParent() == this) { + removeView(mTitleLayout); + } + mTitleLayout = null; + if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) { + initTitle(); + } + + if (mTabScrollView != null && mIncludeTabs) { + ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams(); + if (lp != null) { + lp.width = LayoutParams.WRAP_CONTENT; + lp.height = LayoutParams.MATCH_PARENT; + } + mTabScrollView.setAllowCollapse(true); + } + } + + /** + * Set the window callback used to invoke menu items; used for dispatching home button presses. + * @param cb Window callback to dispatch to + */ + public void setWindowCallback(Window.Callback cb) { + mWindowCallback = cb; + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + //UNUSED removeCallbacks(mTabSelector); + if (mActionMenuPresenter != null) { + mActionMenuPresenter.hideOverflowMenu(); + mActionMenuPresenter.hideSubMenus(); + } + } + + @Override + public boolean shouldDelayChildPressedState() { + return false; + } + + public void initProgress() { + mProgressView = new IcsProgressBar(mContext, null, 0, mProgressStyle); + mProgressView.setId(R.id.abs__progress_horizontal); + mProgressView.setMax(10000); + addView(mProgressView); + } + + public void initIndeterminateProgress() { + mIndeterminateProgressView = new IcsProgressBar(mContext, null, 0, mIndeterminateProgressStyle); + mIndeterminateProgressView.setId(R.id.abs__progress_circular); + addView(mIndeterminateProgressView); + } + + @Override + public void setSplitActionBar(boolean splitActionBar) { + if (mSplitActionBar != splitActionBar) { + if (mMenuView != null) { + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) { + oldParent.removeView(mMenuView); + } + if (splitActionBar) { + if (mSplitView != null) { + mSplitView.addView(mMenuView); + } + } else { + addView(mMenuView); + } + } + if (mSplitView != null) { + mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE); + } + super.setSplitActionBar(splitActionBar); + } + } + + public boolean isSplitActionBar() { + return mSplitActionBar; + } + + public boolean hasEmbeddedTabs() { + return mIncludeTabs; + } + + public void setEmbeddedTabView(ScrollingTabContainerView tabs) { + if (mTabScrollView != null) { + removeView(mTabScrollView); + } + mTabScrollView = tabs; + mIncludeTabs = tabs != null; + if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) { + addView(mTabScrollView); + ViewGroup.LayoutParams lp = mTabScrollView.getLayoutParams(); + lp.width = LayoutParams.WRAP_CONTENT; + lp.height = LayoutParams.MATCH_PARENT; + tabs.setAllowCollapse(true); + } + } + + public void setCallback(OnNavigationListener callback) { + mCallback = callback; + } + + public void setMenu(Menu menu, MenuPresenter.Callback cb) { + if (menu == mOptionsMenu) return; + + if (mOptionsMenu != null) { + mOptionsMenu.removeMenuPresenter(mActionMenuPresenter); + mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter); + } + + MenuBuilder builder = (MenuBuilder) menu; + mOptionsMenu = builder; + if (mMenuView != null) { + final ViewGroup oldParent = (ViewGroup) mMenuView.getParent(); + if (oldParent != null) { + oldParent.removeView(mMenuView); + } + } + if (mActionMenuPresenter == null) { + mActionMenuPresenter = new ActionMenuPresenter(mContext); + mActionMenuPresenter.setCallback(cb); + mActionMenuPresenter.setId(R.id.abs__action_menu_presenter); + mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter(); + } + + ActionMenuView menuView; + final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT); + if (!mSplitActionBar) { + mActionMenuPresenter.setExpandedActionViewsExclusive( + getResources_getBoolean(getContext(), + R.bool.abs__action_bar_expanded_action_views_exclusive)); + configPresenters(builder); + menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + final ViewGroup oldParent = (ViewGroup) menuView.getParent(); + if (oldParent != null && oldParent != this) { + oldParent.removeView(menuView); + } + addView(menuView, layoutParams); + } else { + mActionMenuPresenter.setExpandedActionViewsExclusive(false); + // Allow full screen width in split mode. + mActionMenuPresenter.setWidthLimit( + getContext().getResources().getDisplayMetrics().widthPixels, true); + // No limit to the item count; use whatever will fit. + mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE); + // Span the whole width + layoutParams.width = LayoutParams.MATCH_PARENT; + configPresenters(builder); + menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this); + if (mSplitView != null) { + final ViewGroup oldParent = (ViewGroup) menuView.getParent(); + if (oldParent != null && oldParent != mSplitView) { + oldParent.removeView(menuView); + } + menuView.setVisibility(getAnimatedVisibility()); + mSplitView.addView(menuView, layoutParams); + } else { + // We'll add this later if we missed it this time. + menuView.setLayoutParams(layoutParams); + } + } + mMenuView = menuView; + } + + private void configPresenters(MenuBuilder builder) { + if (builder != null) { + builder.addMenuPresenter(mActionMenuPresenter); + builder.addMenuPresenter(mExpandedMenuPresenter); + } else { + mActionMenuPresenter.initForMenu(mContext, null); + mExpandedMenuPresenter.initForMenu(mContext, null); + mActionMenuPresenter.updateMenuView(true); + mExpandedMenuPresenter.updateMenuView(true); + } + } + + public boolean hasExpandedActionView() { + return mExpandedMenuPresenter != null && + mExpandedMenuPresenter.mCurrentExpandedItem != null; + } + + public void collapseActionView() { + final MenuItemImpl item = mExpandedMenuPresenter == null ? null : + mExpandedMenuPresenter.mCurrentExpandedItem; + if (item != null) { + item.collapseActionView(); + } + } + + public void setCustomNavigationView(View view) { + final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0; + if (mCustomNavView != null && showCustom) { + removeView(mCustomNavView); + } + mCustomNavView = view; + if (mCustomNavView != null && showCustom) { + addView(mCustomNavView); + } + } + + public CharSequence getTitle() { + return mTitle; + } + + /** + * Set the action bar title. This will always replace or override window titles. + * @param title Title to set + * + * @see #setWindowTitle(CharSequence) + */ + public void setTitle(CharSequence title) { + mUserTitle = true; + setTitleImpl(title); + } + + /** + * Set the window title. A window title will always be replaced or overridden by a user title. + * @param title Title to set + * + * @see #setTitle(CharSequence) + */ + public void setWindowTitle(CharSequence title) { + if (!mUserTitle) { + setTitleImpl(title); + } + } + + private void setTitleImpl(CharSequence title) { + mTitle = title; + if (mTitleView != null) { + mTitleView.setText(title); + final boolean visible = mExpandedActionView == null && + (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 && + (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle)); + mTitleLayout.setVisibility(visible ? VISIBLE : GONE); + } + if (mLogoNavItem != null) { + mLogoNavItem.setTitle(title); + } + } + + public CharSequence getSubtitle() { + return mSubtitle; + } + + public void setSubtitle(CharSequence subtitle) { + mSubtitle = subtitle; + if (mSubtitleView != null) { + mSubtitleView.setText(subtitle); + mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE); + final boolean visible = mExpandedActionView == null && + (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0 && + (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle)); + mTitleLayout.setVisibility(visible ? VISIBLE : GONE); + } + } + + public void setHomeButtonEnabled(boolean enable) { + mHomeLayout.setEnabled(enable); + mHomeLayout.setFocusable(enable); + // Make sure the home button has an accurate content description for accessibility. + if (!enable) { + mHomeLayout.setContentDescription(null); + } else if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) { + mHomeLayout.setContentDescription(mContext.getResources().getText( + R.string.abs__action_bar_up_description)); + } else { + mHomeLayout.setContentDescription(mContext.getResources().getText( + R.string.abs__action_bar_home_description)); + } + } + + public void setDisplayOptions(int options) { + final int flagsChanged = mDisplayOptions == -1 ? -1 : options ^ mDisplayOptions; + mDisplayOptions = options; + + if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) { + final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0; + final int vis = showHome && mExpandedActionView == null ? VISIBLE : GONE; + mHomeLayout.setVisibility(vis); + + if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) { + final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0; + mHomeLayout.setUp(setUp); + + // Showing home as up implicitly enables interaction with it. + // In honeycomb it was always enabled, so make this transition + // a bit easier for developers in the common case. + // (It would be silly to show it as up without responding to it.) + if (setUp) { + setHomeButtonEnabled(true); + } + } + + if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) { + final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0; + mHomeLayout.setIcon(logoVis ? mLogo : mIcon); + } + + if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) { + if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) { + initTitle(); + } else { + removeView(mTitleLayout); + } + } + + if (mTitleLayout != null && (flagsChanged & + (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) { + final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0; + mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE); + mTitleLayout.setEnabled(!showHome && homeAsUp); + } + + if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) { + if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { + addView(mCustomNavView); + } else { + removeView(mCustomNavView); + } + } + + requestLayout(); + } else { + invalidate(); + } + + // Make sure the home button has an accurate content description for accessibility. + if (!mHomeLayout.isEnabled()) { + mHomeLayout.setContentDescription(null); + } else if ((options & ActionBar.DISPLAY_HOME_AS_UP) != 0) { + mHomeLayout.setContentDescription(mContext.getResources().getText( + R.string.abs__action_bar_up_description)); + } else { + mHomeLayout.setContentDescription(mContext.getResources().getText( + R.string.abs__action_bar_home_description)); + } + } + + public void setIcon(Drawable icon) { + mIcon = icon; + if (icon != null && + ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) { + mHomeLayout.setIcon(icon); + } + } + + public void setIcon(int resId) { + setIcon(mContext.getResources().getDrawable(resId)); + } + + public void setLogo(Drawable logo) { + mLogo = logo; + if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) { + mHomeLayout.setIcon(logo); + } + } + + public void setLogo(int resId) { + setLogo(mContext.getResources().getDrawable(resId)); + } + + public void setNavigationMode(int mode) { + final int oldMode = mNavigationMode; + if (mode != oldMode) { + switch (oldMode) { + case ActionBar.NAVIGATION_MODE_LIST: + if (mListNavLayout != null) { + removeView(mListNavLayout); + } + break; + case ActionBar.NAVIGATION_MODE_TABS: + if (mTabScrollView != null && mIncludeTabs) { + removeView(mTabScrollView); + } + } + + switch (mode) { + case ActionBar.NAVIGATION_MODE_LIST: + if (mSpinner == null) { + mSpinner = new IcsSpinner(mContext, null, + R.attr.actionDropDownStyle); + mListNavLayout = (IcsLinearLayout) LayoutInflater.from(mContext) + .inflate(R.layout.abs__action_bar_tab_bar_view, null); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); + params.gravity = Gravity.CENTER; + mListNavLayout.addView(mSpinner, params); + } + if (mSpinner.getAdapter() != mSpinnerAdapter) { + mSpinner.setAdapter(mSpinnerAdapter); + } + mSpinner.setOnItemSelectedListener(mNavItemSelectedListener); + addView(mListNavLayout); + break; + case ActionBar.NAVIGATION_MODE_TABS: + if (mTabScrollView != null && mIncludeTabs) { + addView(mTabScrollView); + } + break; + } + mNavigationMode = mode; + requestLayout(); + } + } + + public void setDropdownAdapter(SpinnerAdapter adapter) { + mSpinnerAdapter = adapter; + if (mSpinner != null) { + mSpinner.setAdapter(adapter); + } + } + + public SpinnerAdapter getDropdownAdapter() { + return mSpinnerAdapter; + } + + public void setDropdownSelectedPosition(int position) { + mSpinner.setSelection(position); + } + + public int getDropdownSelectedPosition() { + return mSpinner.getSelectedItemPosition(); + } + + public View getCustomNavigationView() { + return mCustomNavView; + } + + public int getNavigationMode() { + return mNavigationMode; + } + + public int getDisplayOptions() { + return mDisplayOptions; + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + // Used by custom nav views if they don't supply layout params. Everything else + // added to an ActionBarView should have them already. + return new ActionBar.LayoutParams(DEFAULT_CUSTOM_GRAVITY); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + addView(mHomeLayout); + + if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { + final ViewParent parent = mCustomNavView.getParent(); + if (parent != this) { + if (parent instanceof ViewGroup) { + ((ViewGroup) parent).removeView(mCustomNavView); + } + addView(mCustomNavView); + } + } + } + + private void initTitle() { + if (mTitleLayout == null) { + LayoutInflater inflater = LayoutInflater.from(getContext()); + mTitleLayout = (LinearLayout) inflater.inflate(R.layout.abs__action_bar_title_item, + this, false); + mTitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_title); + mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_subtitle); + mTitleUpView = mTitleLayout.findViewById(R.id.abs__up); + + mTitleLayout.setOnClickListener(mUpClickListener); + + if (mTitleStyleRes != 0) { + mTitleView.setTextAppearance(mContext, mTitleStyleRes); + } + if (mTitle != null) { + mTitleView.setText(mTitle); + } + + if (mSubtitleStyleRes != 0) { + mSubtitleView.setTextAppearance(mContext, mSubtitleStyleRes); + } + if (mSubtitle != null) { + mSubtitleView.setText(mSubtitle); + mSubtitleView.setVisibility(VISIBLE); + } + + final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0; + final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0; + mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE); + mTitleLayout.setEnabled(homeAsUp && !showHome); + } + + addView(mTitleLayout); + if (mExpandedActionView != null || + (TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) { + // Don't show while in expanded mode or with empty text + mTitleLayout.setVisibility(GONE); + } + } + + public void setContextView(ActionBarContextView view) { + mContextView = view; + } + + public void setCollapsable(boolean collapsable) { + mIsCollapsable = collapsable; + } + + public boolean isCollapsed() { + return mIsCollapsed; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int childCount = getChildCount(); + if (mIsCollapsable) { + int visibleChildren = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + if (child.getVisibility() != GONE && + !(child == mMenuView && mMenuView.getChildCount() == 0)) { + visibleChildren++; + } + } + + if (visibleChildren == 0) { + // No size for an empty action bar when collapsable. + setMeasuredDimension(0, 0); + mIsCollapsed = true; + return; + } + } + mIsCollapsed = false; + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + if (widthMode != MeasureSpec.EXACTLY) { + throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + + "with android:layout_width=\"match_parent\" (or fill_parent)"); + } + + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + if (heightMode != MeasureSpec.AT_MOST) { + throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + + "with android:layout_height=\"wrap_content\""); + } + + int contentWidth = MeasureSpec.getSize(widthMeasureSpec); + + int maxHeight = mContentHeight > 0 ? + mContentHeight : MeasureSpec.getSize(heightMeasureSpec); + + final int verticalPadding = getPaddingTop() + getPaddingBottom(); + final int paddingLeft = getPaddingLeft(); + final int paddingRight = getPaddingRight(); + final int height = maxHeight - verticalPadding; + final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); + + int availableWidth = contentWidth - paddingLeft - paddingRight; + int leftOfCenter = availableWidth / 2; + int rightOfCenter = leftOfCenter; + + HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; + + if (homeLayout.getVisibility() != GONE) { + final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams(); + int homeWidthSpec; + if (lp.width < 0) { + homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST); + } else { + homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); + } + homeLayout.measure(homeWidthSpec, + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset(); + availableWidth = Math.max(0, availableWidth - homeWidth); + leftOfCenter = Math.max(0, availableWidth - homeWidth); + } + + if (mMenuView != null && mMenuView.getParent() == this) { + availableWidth = measureChildView(mMenuView, availableWidth, + childSpecHeight, 0); + rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth()); + } + + if (mIndeterminateProgressView != null && + mIndeterminateProgressView.getVisibility() != GONE) { + availableWidth = measureChildView(mIndeterminateProgressView, availableWidth, + childSpecHeight, 0); + rightOfCenter = Math.max(0, + rightOfCenter - mIndeterminateProgressView.getMeasuredWidth()); + } + + final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && + (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; + + if (mExpandedActionView == null) { + switch (mNavigationMode) { + case ActionBar.NAVIGATION_MODE_LIST: + if (mListNavLayout != null) { + final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; + availableWidth = Math.max(0, availableWidth - itemPaddingSize); + leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); + mListNavLayout.measure( + MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + final int listNavWidth = mListNavLayout.getMeasuredWidth(); + availableWidth = Math.max(0, availableWidth - listNavWidth); + leftOfCenter = Math.max(0, leftOfCenter - listNavWidth); + } + break; + case ActionBar.NAVIGATION_MODE_TABS: + if (mTabScrollView != null) { + final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; + availableWidth = Math.max(0, availableWidth - itemPaddingSize); + leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); + mTabScrollView.measure( + MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + final int tabWidth = mTabScrollView.getMeasuredWidth(); + availableWidth = Math.max(0, availableWidth - tabWidth); + leftOfCenter = Math.max(0, leftOfCenter - tabWidth); + } + break; + } + } + + View customView = null; + if (mExpandedActionView != null) { + customView = mExpandedActionView; + } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && + mCustomNavView != null) { + customView = mCustomNavView; + } + + if (customView != null) { + final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams()); + final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? + (ActionBar.LayoutParams) lp : null; + + int horizontalMargin = 0; + int verticalMargin = 0; + if (ablp != null) { + horizontalMargin = ablp.leftMargin + ablp.rightMargin; + verticalMargin = ablp.topMargin + ablp.bottomMargin; + } + + // If the action bar is wrapping to its content height, don't allow a custom + // view to MATCH_PARENT. + int customNavHeightMode; + if (mContentHeight <= 0) { + customNavHeightMode = MeasureSpec.AT_MOST; + } else { + customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? + MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; + } + final int customNavHeight = Math.max(0, + (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin); + + final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? + MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; + int customNavWidth = Math.max(0, + (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth) + - horizontalMargin); + final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) & + Gravity.HORIZONTAL_GRAVITY_MASK; + + // Centering a custom view is treated specially; we try to center within the whole + // action bar rather than in the available space. + if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.MATCH_PARENT) { + customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2; + } + + customView.measure( + MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode), + MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode)); + availableWidth -= horizontalMargin + customView.getMeasuredWidth(); + } + + if (mExpandedActionView == null && showTitle) { + availableWidth = measureChildView(mTitleLayout, availableWidth, + MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0); + leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth()); + } + + if (mContentHeight <= 0) { + int measuredHeight = 0; + for (int i = 0; i < childCount; i++) { + View v = getChildAt(i); + int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; + if (paddedViewHeight > measuredHeight) { + measuredHeight = paddedViewHeight; + } + } + setMeasuredDimension(contentWidth, measuredHeight); + } else { + setMeasuredDimension(contentWidth, maxHeight); + } + + if (mContextView != null) { + mContextView.setContentHeight(getMeasuredHeight()); + } + + if (mProgressView != null && mProgressView.getVisibility() != GONE) { + mProgressView.measure(MeasureSpec.makeMeasureSpec( + contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int x = getPaddingLeft(); + final int y = getPaddingTop(); + final int contentHeight = b - t - getPaddingTop() - getPaddingBottom(); + + if (contentHeight <= 0) { + // Nothing to do if we can't see anything. + return; + } + + HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; + if (homeLayout.getVisibility() != GONE) { + final int leftOffset = homeLayout.getLeftOffset(); + x += positionChild(homeLayout, x + leftOffset, y, contentHeight) + leftOffset; + } + + if (mExpandedActionView == null) { + final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && + (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; + if (showTitle) { + x += positionChild(mTitleLayout, x, y, contentHeight); + } + + switch (mNavigationMode) { + case ActionBar.NAVIGATION_MODE_STANDARD: + break; + case ActionBar.NAVIGATION_MODE_LIST: + if (mListNavLayout != null) { + if (showTitle) x += mItemPadding; + x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding; + } + break; + case ActionBar.NAVIGATION_MODE_TABS: + if (mTabScrollView != null) { + if (showTitle) x += mItemPadding; + x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding; + } + break; + } + } + + int menuLeft = r - l - getPaddingRight(); + if (mMenuView != null && mMenuView.getParent() == this) { + positionChildInverse(mMenuView, menuLeft, y, contentHeight); + menuLeft -= mMenuView.getMeasuredWidth(); + } + + if (mIndeterminateProgressView != null && + mIndeterminateProgressView.getVisibility() != GONE) { + positionChildInverse(mIndeterminateProgressView, menuLeft, y, contentHeight); + menuLeft -= mIndeterminateProgressView.getMeasuredWidth(); + } + + View customView = null; + if (mExpandedActionView != null) { + customView = mExpandedActionView; + } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && + mCustomNavView != null) { + customView = mCustomNavView; + } + if (customView != null) { + ViewGroup.LayoutParams lp = customView.getLayoutParams(); + final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? + (ActionBar.LayoutParams) lp : null; + + final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY; + final int navWidth = customView.getMeasuredWidth(); + + int topMargin = 0; + int bottomMargin = 0; + if (ablp != null) { + x += ablp.leftMargin; + menuLeft -= ablp.rightMargin; + topMargin = ablp.topMargin; + bottomMargin = ablp.bottomMargin; + } + + int hgravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + // See if we actually have room to truly center; if not push against left or right. + if (hgravity == Gravity.CENTER_HORIZONTAL) { + final int centeredLeft = ((getRight() - getLeft()) - navWidth) / 2; + if (centeredLeft < x) { + hgravity = Gravity.LEFT; + } else if (centeredLeft + navWidth > menuLeft) { + hgravity = Gravity.RIGHT; + } + } else if (gravity == -1) { + hgravity = Gravity.LEFT; + } + + int xpos = 0; + switch (hgravity) { + case Gravity.CENTER_HORIZONTAL: + xpos = ((getRight() - getLeft()) - navWidth) / 2; + break; + case Gravity.LEFT: + xpos = x; + break; + case Gravity.RIGHT: + xpos = menuLeft - navWidth; + break; + } + + int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + + if (gravity == -1) { + vgravity = Gravity.CENTER_VERTICAL; + } + + int ypos = 0; + switch (vgravity) { + case Gravity.CENTER_VERTICAL: + final int paddedTop = getPaddingTop(); + final int paddedBottom = getBottom() - getTop() - getPaddingBottom(); + ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2; + break; + case Gravity.TOP: + ypos = getPaddingTop() + topMargin; + break; + case Gravity.BOTTOM: + ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight() + - bottomMargin; + break; + } + final int customWidth = customView.getMeasuredWidth(); + customView.layout(xpos, ypos, xpos + customWidth, + ypos + customView.getMeasuredHeight()); + x += customWidth; + } + + if (mProgressView != null) { + mProgressView.bringToFront(); + final int halfProgressHeight = mProgressView.getMeasuredHeight() / 2; + mProgressView.layout(mProgressBarPadding, -halfProgressHeight, + mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight); + } + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { + return new ActionBar.LayoutParams(getContext(), attrs); + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { + if (lp == null) { + lp = generateDefaultLayoutParams(); + } + return lp; + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState state = new SavedState(superState); + + if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) { + state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId(); + } + + state.isOverflowOpen = isOverflowMenuShowing(); + + return state; + } + + @Override + public void onRestoreInstanceState(Parcelable p) { + SavedState state = (SavedState) p; + + super.onRestoreInstanceState(state.getSuperState()); + + if (state.expandedMenuItemId != 0 && + mExpandedMenuPresenter != null && mOptionsMenu != null) { + final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId); + if (item != null) { + item.expandActionView(); + } + } + + if (state.isOverflowOpen) { + postShowOverflowMenu(); + } + } + + static class SavedState extends BaseSavedState { + int expandedMenuItemId; + boolean isOverflowOpen; + + SavedState(Parcelable superState) { + super(superState); + } + + private SavedState(Parcel in) { + super(in); + expandedMenuItemId = in.readInt(); + isOverflowOpen = in.readInt() != 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(expandedMenuItemId); + out.writeInt(isOverflowOpen ? 1 : 0); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + public static class HomeView extends FrameLayout { + private View mUpView; + private ImageView mIconView; + private int mUpWidth; + + public HomeView(Context context) { + this(context, null); + } + + public HomeView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setUp(boolean isUp) { + mUpView.setVisibility(isUp ? VISIBLE : GONE); + } + + public void setIcon(Drawable icon) { + mIconView.setImageDrawable(icon); + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + onPopulateAccessibilityEvent(event); + return true; + } + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + super.onPopulateAccessibilityEvent(event); + } + final CharSequence cdesc = getContentDescription(); + if (!TextUtils.isEmpty(cdesc)) { + event.getText().add(cdesc); + } + } + + @Override + public boolean dispatchHoverEvent(MotionEvent event) { + // Don't allow children to hover; we want this to be treated as a single component. + return onHoverEvent(event); + } + + @Override + protected void onFinishInflate() { + mUpView = findViewById(R.id.abs__up); + mIconView = (ImageView) findViewById(R.id.abs__home); + } + + public int getLeftOffset() { + return mUpView.getVisibility() == GONE ? mUpWidth : 0; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0); + final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); + mUpWidth = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin; + int width = mUpView.getVisibility() == GONE ? 0 : mUpWidth; + int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin; + measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0); + final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); + width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin; + height = Math.max(height, + iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin); + + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final int heightMode = MeasureSpec.getMode(heightMeasureSpec); + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + final int heightSize = MeasureSpec.getSize(heightMeasureSpec); + + switch (widthMode) { + case MeasureSpec.AT_MOST: + width = Math.min(width, widthSize); + break; + case MeasureSpec.EXACTLY: + width = widthSize; + break; + case MeasureSpec.UNSPECIFIED: + default: + break; + } + switch (heightMode) { + case MeasureSpec.AT_MOST: + height = Math.min(height, heightSize); + break; + case MeasureSpec.EXACTLY: + height = heightSize; + break; + case MeasureSpec.UNSPECIFIED: + default: + break; + } + setMeasuredDimension(width, height); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + final int vCenter = (b - t) / 2; + //UNUSED int width = r - l; + int upOffset = 0; + if (mUpView.getVisibility() != GONE) { + final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams(); + final int upHeight = mUpView.getMeasuredHeight(); + final int upWidth = mUpView.getMeasuredWidth(); + final int upTop = vCenter - upHeight / 2; + mUpView.layout(0, upTop, upWidth, upTop + upHeight); + upOffset = upLp.leftMargin + upWidth + upLp.rightMargin; + //UNUSED width -= upOffset; + l += upOffset; + } + final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams(); + final int iconHeight = mIconView.getMeasuredHeight(); + final int iconWidth = mIconView.getMeasuredWidth(); + final int hCenter = (r - l) / 2; + final int iconLeft = upOffset + Math.max(iconLp.leftMargin, hCenter - iconWidth / 2); + final int iconTop = Math.max(iconLp.topMargin, vCenter - iconHeight / 2); + mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight); + } + } + + private class ExpandedActionViewMenuPresenter implements MenuPresenter { + MenuBuilder mMenu; + MenuItemImpl mCurrentExpandedItem; + + @Override + public void initForMenu(Context context, MenuBuilder menu) { + // Clear the expanded action view when menus change. + if (mMenu != null && mCurrentExpandedItem != null) { + mMenu.collapseItemActionView(mCurrentExpandedItem); + } + mMenu = menu; + } + + @Override + public MenuView getMenuView(ViewGroup root) { + return null; + } + + @Override + public void updateMenuView(boolean cleared) { + // Make sure the expanded item we have is still there. + if (mCurrentExpandedItem != null) { + boolean found = false; + + if (mMenu != null) { + final int count = mMenu.size(); + for (int i = 0; i < count; i++) { + final MenuItem item = mMenu.getItem(i); + if (item == mCurrentExpandedItem) { + found = true; + break; + } + } + } + + if (!found) { + // The item we had expanded disappeared. Collapse. + collapseItemActionView(mMenu, mCurrentExpandedItem); + } + } + } + + @Override + public void setCallback(Callback cb) { + } + + @Override + public boolean onSubMenuSelected(SubMenuBuilder subMenu) { + return false; + } + + @Override + public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { + } + + @Override + public boolean flagActionItems() { + return false; + } + + @Override + public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { + mExpandedActionView = item.getActionView(); + mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(/* TODO getResources() */)); + mCurrentExpandedItem = item; + if (mExpandedActionView.getParent() != ActionBarView.this) { + addView(mExpandedActionView); + } + if (mExpandedHomeLayout.getParent() != ActionBarView.this) { + addView(mExpandedHomeLayout); + } + mHomeLayout.setVisibility(GONE); + if (mTitleLayout != null) mTitleLayout.setVisibility(GONE); + if (mTabScrollView != null) mTabScrollView.setVisibility(GONE); + if (mSpinner != null) mSpinner.setVisibility(GONE); + if (mCustomNavView != null) mCustomNavView.setVisibility(GONE); + requestLayout(); + item.setActionViewExpanded(true); + + if (mExpandedActionView instanceof CollapsibleActionView) { + ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded(); + } + + return true; + } + + @Override + public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { + // Do this before detaching the actionview from the hierarchy, in case + // it needs to dismiss the soft keyboard, etc. + if (mExpandedActionView instanceof CollapsibleActionView) { + ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed(); + } + + removeView(mExpandedActionView); + removeView(mExpandedHomeLayout); + mExpandedActionView = null; + if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) { + mHomeLayout.setVisibility(VISIBLE); + } + if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) { + if (mTitleLayout == null) { + initTitle(); + } else { + mTitleLayout.setVisibility(VISIBLE); + } + } + if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) { + mTabScrollView.setVisibility(VISIBLE); + } + if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) { + mSpinner.setVisibility(VISIBLE); + } + if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) { + mCustomNavView.setVisibility(VISIBLE); + } + mExpandedHomeLayout.setIcon(null); + mCurrentExpandedItem = null; + requestLayout(); + item.setActionViewExpanded(false); + + return true; + } + + @Override + public int getId() { + return 0; + } + + @Override + public Parcelable onSaveInstanceState() { + return null; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java new file mode 100644 index 000000000..fa3698f3b --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingButton.java @@ -0,0 +1,40 @@ +package com.actionbarsherlock.internal.widget; + +import java.util.Locale; +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.Button; + +public class CapitalizingButton extends Button { + private static final boolean SANS_ICE_CREAM = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH; + private static final boolean IS_GINGERBREAD = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; + + private static final int[] R_styleable_Button = new int[] { + android.R.attr.textAllCaps + }; + private static final int R_styleable_Button_textAllCaps = 0; + + private boolean mAllCaps; + + public CapitalizingButton(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R_styleable_Button); + mAllCaps = a.getBoolean(R_styleable_Button_textAllCaps, true); + a.recycle(); + } + + public void setTextCompat(CharSequence text) { + if (SANS_ICE_CREAM && mAllCaps && text != null) { + if (IS_GINGERBREAD) { + setText(text.toString().toUpperCase(Locale.ROOT)); + } else { + setText(text.toString().toUpperCase()); + } + } else { + setText(text); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java new file mode 100644 index 000000000..cae8b8aed --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CapitalizingTextView.java @@ -0,0 +1,50 @@ +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.TextView; + +import java.util.Locale; + +public class CapitalizingTextView extends TextView { + private static final boolean SANS_ICE_CREAM = Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH; + private static final boolean IS_GINGERBREAD = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD; + + private static final int[] R_styleable_TextView = new int[] { + android.R.attr.textAllCaps + }; + private static final int R_styleable_TextView_textAllCaps = 0; + + private boolean mAllCaps; + + public CapitalizingTextView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CapitalizingTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R_styleable_TextView, defStyle, 0); + mAllCaps = a.getBoolean(R_styleable_TextView_textAllCaps, true); + a.recycle(); + } + + public void setTextCompat(CharSequence text) { + if (SANS_ICE_CREAM && mAllCaps && text != null) { + if (IS_GINGERBREAD) { + try { + setText(text.toString().toUpperCase(Locale.ROOT)); + } catch (NoSuchFieldError e) { + //Some manufacturer broke Locale.ROOT. See #572. + setText(text.toString().toUpperCase()); + } + } else { + setText(text.toString().toUpperCase()); + } + } else { + setText(text); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java new file mode 100644 index 000000000..14f092c81 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/CollapsibleActionViewWrapper.java @@ -0,0 +1,30 @@ +package com.actionbarsherlock.internal.widget; + +import android.view.View; +import android.widget.FrameLayout; +import com.actionbarsherlock.view.CollapsibleActionView; + +/** + * Wraps an ABS collapsible action view in a native container that delegates the calls. + */ +public class CollapsibleActionViewWrapper extends FrameLayout implements android.view.CollapsibleActionView { + private final CollapsibleActionView child; + + public CollapsibleActionViewWrapper(View child) { + super(child.getContext()); + this.child = (CollapsibleActionView) child; + addView(child); + } + + @Override public void onActionViewExpanded() { + child.onActionViewExpanded(); + } + + @Override public void onActionViewCollapsed() { + child.onActionViewCollapsed(); + } + + public View unwrap() { + return getChildAt(0); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java new file mode 100644 index 000000000..ad1b4f0a8 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/FakeDialogPhoneWindow.java @@ -0,0 +1,64 @@ +package com.actionbarsherlock.internal.widget; + +import static android.view.View.MeasureSpec.EXACTLY; +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.widget.LinearLayout; +import com.actionbarsherlock.R; + +public class FakeDialogPhoneWindow extends LinearLayout { + final TypedValue mMinWidthMajor = new TypedValue(); + final TypedValue mMinWidthMinor = new TypedValue(); + + public FakeDialogPhoneWindow(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockTheme); + + a.getValue(R.styleable.SherlockTheme_windowMinWidthMajor, mMinWidthMajor); + a.getValue(R.styleable.SherlockTheme_windowMinWidthMinor, mMinWidthMinor); + + a.recycle(); + } + + /* Stolen from PhoneWindow */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); + final boolean isPortrait = metrics.widthPixels < metrics.heightPixels; + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + int width = getMeasuredWidth(); + boolean measure = false; + + widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY); + + final TypedValue tv = isPortrait ? mMinWidthMinor : mMinWidthMajor; + + if (tv.type != TypedValue.TYPE_NULL) { + final int min; + if (tv.type == TypedValue.TYPE_DIMENSION) { + min = (int)tv.getDimension(metrics); + } else if (tv.type == TypedValue.TYPE_FRACTION) { + min = (int)tv.getFraction(metrics.widthPixels, metrics.widthPixels); + } else { + min = 0; + } + + if (width < min) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec(min, EXACTLY); + measure = true; + } + } + + // TODO: Support height? + + if (measure) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java new file mode 100644 index 000000000..ce0cb3bca --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAbsSpinner.java @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.database.DataSetObserver; +import android.graphics.Rect; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.View; +import android.view.ViewGroup; +import android.widget.SpinnerAdapter; + +/** + * An abstract base class for spinner widgets. SDK users will probably not + * need to use this class. + * + * @attr ref android.R.styleable#AbsSpinner_entries + */ +public abstract class IcsAbsSpinner extends IcsAdapterView { + private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + + SpinnerAdapter mAdapter; + + int mHeightMeasureSpec; + int mWidthMeasureSpec; + boolean mBlockLayoutRequests; + + int mSelectionLeftPadding = 0; + int mSelectionTopPadding = 0; + int mSelectionRightPadding = 0; + int mSelectionBottomPadding = 0; + final Rect mSpinnerPadding = new Rect(); + + final RecycleBin mRecycler = new RecycleBin(); + private DataSetObserver mDataSetObserver; + + /** Temporary frame to hold a child View's frame rectangle */ + private Rect mTouchFrame; + + public IcsAbsSpinner(Context context) { + super(context); + initAbsSpinner(); + } + + public IcsAbsSpinner(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public IcsAbsSpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initAbsSpinner(); + + /* + TypedArray a = context.obtainStyledAttributes(attrs, + com.android.internal.R.styleable.AbsSpinner, defStyle, 0); + + CharSequence[] entries = a.getTextArray(R.styleable.AbsSpinner_entries); + if (entries != null) { + ArrayAdapter adapter = + new ArrayAdapter(context, + R.layout.simple_spinner_item, entries); + adapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item); + setAdapter(adapter); + } + + a.recycle(); + */ + } + + /** + * Common code for different constructor flavors + */ + private void initAbsSpinner() { + setFocusable(true); + setWillNotDraw(false); + } + + /** + * The Adapter is used to provide the data which backs this Spinner. + * It also provides methods to transform spinner items based on their position + * relative to the selected item. + * @param adapter The SpinnerAdapter to use for this Spinner + */ + @Override + public void setAdapter(SpinnerAdapter adapter) { + if (null != mAdapter) { + mAdapter.unregisterDataSetObserver(mDataSetObserver); + resetList(); + } + + mAdapter = adapter; + + mOldSelectedPosition = INVALID_POSITION; + mOldSelectedRowId = INVALID_ROW_ID; + + if (mAdapter != null) { + mOldItemCount = mItemCount; + mItemCount = mAdapter.getCount(); + checkFocus(); + + mDataSetObserver = new AdapterDataSetObserver(); + mAdapter.registerDataSetObserver(mDataSetObserver); + + int position = mItemCount > 0 ? 0 : INVALID_POSITION; + + setSelectedPositionInt(position); + setNextSelectedPositionInt(position); + + if (mItemCount == 0) { + // Nothing selected + checkSelectionChanged(); + } + + } else { + checkFocus(); + resetList(); + // Nothing selected + checkSelectionChanged(); + } + + requestLayout(); + } + + /** + * Clear out all children from the list + */ + void resetList() { + mDataChanged = false; + mNeedSync = false; + + removeAllViewsInLayout(); + mOldSelectedPosition = INVALID_POSITION; + mOldSelectedRowId = INVALID_ROW_ID; + + setSelectedPositionInt(INVALID_POSITION); + setNextSelectedPositionInt(INVALID_POSITION); + invalidate(); + } + + /** + * @see android.view.View#measure(int, int) + * + * Figure out the dimensions of this Spinner. The width comes from + * the widthMeasureSpec as Spinnners can't have their width set to + * UNSPECIFIED. The height is based on the height of the selected item + * plus padding. + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int widthSize; + int heightSize; + + final int mPaddingLeft = getPaddingLeft(); + final int mPaddingTop = getPaddingTop(); + final int mPaddingRight = getPaddingRight(); + final int mPaddingBottom = getPaddingBottom(); + + mSpinnerPadding.left = mPaddingLeft > mSelectionLeftPadding ? mPaddingLeft + : mSelectionLeftPadding; + mSpinnerPadding.top = mPaddingTop > mSelectionTopPadding ? mPaddingTop + : mSelectionTopPadding; + mSpinnerPadding.right = mPaddingRight > mSelectionRightPadding ? mPaddingRight + : mSelectionRightPadding; + mSpinnerPadding.bottom = mPaddingBottom > mSelectionBottomPadding ? mPaddingBottom + : mSelectionBottomPadding; + + if (mDataChanged) { + handleDataChanged(); + } + + int preferredHeight = 0; + int preferredWidth = 0; + boolean needsMeasuring = true; + + int selectedPosition = getSelectedItemPosition(); + if (selectedPosition >= 0 && mAdapter != null && selectedPosition < mAdapter.getCount()) { + // Try looking in the recycler. (Maybe we were measured once already) + View view = mRecycler.get(selectedPosition); + if (view == null) { + // Make a new one + view = mAdapter.getView(selectedPosition, null, this); + } + + if (view != null) { + // Put in recycler for re-measuring and/or layout + mRecycler.put(selectedPosition, view); + } + + if (view != null) { + if (view.getLayoutParams() == null) { + mBlockLayoutRequests = true; + view.setLayoutParams(generateDefaultLayoutParams()); + mBlockLayoutRequests = false; + } + measureChild(view, widthMeasureSpec, heightMeasureSpec); + + preferredHeight = getChildHeight(view) + mSpinnerPadding.top + mSpinnerPadding.bottom; + preferredWidth = getChildWidth(view) + mSpinnerPadding.left + mSpinnerPadding.right; + + needsMeasuring = false; + } + } + + if (needsMeasuring) { + // No views -- just use padding + preferredHeight = mSpinnerPadding.top + mSpinnerPadding.bottom; + if (widthMode == MeasureSpec.UNSPECIFIED) { + preferredWidth = mSpinnerPadding.left + mSpinnerPadding.right; + } + } + + preferredHeight = Math.max(preferredHeight, getSuggestedMinimumHeight()); + preferredWidth = Math.max(preferredWidth, getSuggestedMinimumWidth()); + + if (IS_HONEYCOMB) { + heightSize = resolveSizeAndState(preferredHeight, heightMeasureSpec, 0); + widthSize = resolveSizeAndState(preferredWidth, widthMeasureSpec, 0); + } else { + heightSize = resolveSize(preferredHeight, heightMeasureSpec); + widthSize = resolveSize(preferredWidth, widthMeasureSpec); + } + + setMeasuredDimension(widthSize, heightSize); + mHeightMeasureSpec = heightMeasureSpec; + mWidthMeasureSpec = widthMeasureSpec; + } + + int getChildHeight(View child) { + return child.getMeasuredHeight(); + } + + int getChildWidth(View child) { + return child.getMeasuredWidth(); + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT); + } + + void recycleAllViews() { + final int childCount = getChildCount(); + final IcsAbsSpinner.RecycleBin recycleBin = mRecycler; + final int position = mFirstPosition; + + // All views go in recycler + for (int i = 0; i < childCount; i++) { + View v = getChildAt(i); + int index = position + i; + recycleBin.put(index, v); + } + } + + /** + * Jump directly to a specific item in the adapter data. + */ + public void setSelection(int position, boolean animate) { + // Animate only if requested position is already on screen somewhere + boolean shouldAnimate = animate && mFirstPosition <= position && + position <= mFirstPosition + getChildCount() - 1; + setSelectionInt(position, shouldAnimate); + } + + @Override + public void setSelection(int position) { + setNextSelectedPositionInt(position); + requestLayout(); + invalidate(); + } + + + /** + * Makes the item at the supplied position selected. + * + * @param position Position to select + * @param animate Should the transition be animated + * + */ + void setSelectionInt(int position, boolean animate) { + if (position != mOldSelectedPosition) { + mBlockLayoutRequests = true; + int delta = position - mSelectedPosition; + setNextSelectedPositionInt(position); + layout(delta, animate); + mBlockLayoutRequests = false; + } + } + + abstract void layout(int delta, boolean animate); + + @Override + public View getSelectedView() { + if (mItemCount > 0 && mSelectedPosition >= 0) { + return getChildAt(mSelectedPosition - mFirstPosition); + } else { + return null; + } + } + + /** + * Override to prevent spamming ourselves with layout requests + * as we place views + * + * @see android.view.View#requestLayout() + */ + @Override + public void requestLayout() { + if (!mBlockLayoutRequests) { + super.requestLayout(); + } + } + + @Override + public SpinnerAdapter getAdapter() { + return mAdapter; + } + + @Override + public int getCount() { + return mItemCount; + } + + /** + * Maps a point to a position in the list. + * + * @param x X in local coordinate + * @param y Y in local coordinate + * @return The position of the item which contains the specified point, or + * {@link #INVALID_POSITION} if the point does not intersect an item. + */ + public int pointToPosition(int x, int y) { + Rect frame = mTouchFrame; + if (frame == null) { + mTouchFrame = new Rect(); + frame = mTouchFrame; + } + + final int count = getChildCount(); + for (int i = count - 1; i >= 0; i--) { + View child = getChildAt(i); + if (child.getVisibility() == View.VISIBLE) { + child.getHitRect(frame); + if (frame.contains(x, y)) { + return mFirstPosition + i; + } + } + } + return INVALID_POSITION; + } + + static class SavedState extends BaseSavedState { + long selectedId; + int position; + + /** + * Constructor called from {@link AbsSpinner#onSaveInstanceState()} + */ + SavedState(Parcelable superState) { + super(superState); + } + + /** + * Constructor called from {@link #CREATOR} + */ + private SavedState(Parcel in) { + super(in); + selectedId = in.readLong(); + position = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeLong(selectedId); + out.writeInt(position); + } + + @Override + public String toString() { + return "AbsSpinner.SavedState{" + + Integer.toHexString(System.identityHashCode(this)) + + " selectedId=" + selectedId + + " position=" + position + "}"; + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + @Override + public Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + ss.selectedId = getSelectedItemId(); + if (ss.selectedId >= 0) { + ss.position = getSelectedItemPosition(); + } else { + ss.position = INVALID_POSITION; + } + return ss; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState) state; + + super.onRestoreInstanceState(ss.getSuperState()); + + if (ss.selectedId >= 0) { + mDataChanged = true; + mNeedSync = true; + mSyncRowId = ss.selectedId; + mSyncPosition = ss.position; + mSyncMode = SYNC_SELECTED_POSITION; + requestLayout(); + } + } + + class RecycleBin { + private final SparseArray mScrapHeap = new SparseArray(); + + public void put(int position, View v) { + mScrapHeap.put(position, v); + } + + View get(int position) { + // System.out.print("Looking for " + position); + View result = mScrapHeap.get(position); + if (result != null) { + // System.out.println(" HIT"); + mScrapHeap.delete(position); + } else { + // System.out.println(" MISS"); + } + return result; + } + + void clear() { + final SparseArray scrapHeap = mScrapHeap; + final int count = scrapHeap.size(); + for (int i = 0; i < count; i++) { + final View view = scrapHeap.valueAt(i); + if (view != null) { + removeDetachedView(view, true); + } + } + scrapHeap.clear(); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java new file mode 100644 index 000000000..c786dc5c1 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsAdapterView.java @@ -0,0 +1,1160 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.database.DataSetObserver; +import android.os.Parcelable; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.ContextMenu; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.ViewDebug; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.Adapter; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ListView; + + +/** + * An AdapterView is a view whose children are determined by an {@link Adapter}. + * + *

+ * See {@link ListView}, {@link GridView}, {@link Spinner} and + * {@link Gallery} for commonly used subclasses of AdapterView. + * + *

+ *

Developer Guides

+ *

For more information about using AdapterView, read the + * Binding to Data with AdapterView + * developer guide.

+ */ +public abstract class IcsAdapterView extends ViewGroup { + + /** + * The item view type returned by {@link Adapter#getItemViewType(int)} when + * the adapter does not want the item's view recycled. + */ + public static final int ITEM_VIEW_TYPE_IGNORE = -1; + + /** + * The item view type returned by {@link Adapter#getItemViewType(int)} when + * the item is a header or footer. + */ + public static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2; + + /** + * The position of the first child displayed + */ + @ViewDebug.ExportedProperty(category = "scrolling") + int mFirstPosition = 0; + + /** + * The offset in pixels from the top of the AdapterView to the top + * of the view to select during the next layout. + */ + int mSpecificTop; + + /** + * Position from which to start looking for mSyncRowId + */ + int mSyncPosition; + + /** + * Row id to look for when data has changed + */ + long mSyncRowId = INVALID_ROW_ID; + + /** + * Height of the view when mSyncPosition and mSyncRowId where set + */ + long mSyncHeight; + + /** + * True if we need to sync to mSyncRowId + */ + boolean mNeedSync = false; + + /** + * Indicates whether to sync based on the selection or position. Possible + * values are {@link #SYNC_SELECTED_POSITION} or + * {@link #SYNC_FIRST_POSITION}. + */ + int mSyncMode; + + /** + * Our height after the last layout + */ + private int mLayoutHeight; + + /** + * Sync based on the selected child + */ + static final int SYNC_SELECTED_POSITION = 0; + + /** + * Sync based on the first child displayed + */ + static final int SYNC_FIRST_POSITION = 1; + + /** + * Maximum amount of time to spend in {@link #findSyncPosition()} + */ + static final int SYNC_MAX_DURATION_MILLIS = 100; + + /** + * Indicates that this view is currently being laid out. + */ + boolean mInLayout = false; + + /** + * The listener that receives notifications when an item is selected. + */ + OnItemSelectedListener mOnItemSelectedListener; + + /** + * The listener that receives notifications when an item is clicked. + */ + OnItemClickListener mOnItemClickListener; + + /** + * The listener that receives notifications when an item is long clicked. + */ + OnItemLongClickListener mOnItemLongClickListener; + + /** + * True if the data has changed since the last layout + */ + boolean mDataChanged; + + /** + * The position within the adapter's data set of the item to select + * during the next layout. + */ + @ViewDebug.ExportedProperty(category = "list") + int mNextSelectedPosition = INVALID_POSITION; + + /** + * The item id of the item to select during the next layout. + */ + long mNextSelectedRowId = INVALID_ROW_ID; + + /** + * The position within the adapter's data set of the currently selected item. + */ + @ViewDebug.ExportedProperty(category = "list") + int mSelectedPosition = INVALID_POSITION; + + /** + * The item id of the currently selected item. + */ + long mSelectedRowId = INVALID_ROW_ID; + + /** + * View to show if there are no items to show. + */ + private View mEmptyView; + + /** + * The number of items in the current adapter. + */ + @ViewDebug.ExportedProperty(category = "list") + int mItemCount; + + /** + * The number of items in the adapter before a data changed event occurred. + */ + int mOldItemCount; + + /** + * Represents an invalid position. All valid positions are in the range 0 to 1 less than the + * number of items in the current adapter. + */ + public static final int INVALID_POSITION = -1; + + /** + * Represents an empty or invalid row id + */ + public static final long INVALID_ROW_ID = Long.MIN_VALUE; + + /** + * The last selected position we used when notifying + */ + int mOldSelectedPosition = INVALID_POSITION; + + /** + * The id of the last selected position we used when notifying + */ + long mOldSelectedRowId = INVALID_ROW_ID; + + /** + * Indicates what focusable state is requested when calling setFocusable(). + * In addition to this, this view has other criteria for actually + * determining the focusable state (such as whether its empty or the text + * filter is shown). + * + * @see #setFocusable(boolean) + * @see #checkFocus() + */ + private boolean mDesiredFocusableState; + private boolean mDesiredFocusableInTouchModeState; + + private SelectionNotifier mSelectionNotifier; + /** + * When set to true, calls to requestLayout() will not propagate up the parent hierarchy. + * This is used to layout the children during a layout pass. + */ + boolean mBlockLayoutRequests = false; + + public IcsAdapterView(Context context) { + super(context); + } + + public IcsAdapterView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public IcsAdapterView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + /** + * Register a callback to be invoked when an item in this AdapterView has + * been clicked. + * + * @param listener The callback that will be invoked. + */ + public void setOnItemClickListener(OnItemClickListener listener) { + mOnItemClickListener = listener; + } + + /** + * @return The callback to be invoked with an item in this AdapterView has + * been clicked, or null id no callback has been set. + */ + public final OnItemClickListener getOnItemClickListener() { + return mOnItemClickListener; + } + + /** + * Call the OnItemClickListener, if it is defined. + * + * @param view The view within the AdapterView that was clicked. + * @param position The position of the view in the adapter. + * @param id The row id of the item that was clicked. + * @return True if there was an assigned OnItemClickListener that was + * called, false otherwise is returned. + */ + public boolean performItemClick(View view, int position, long id) { + if (mOnItemClickListener != null) { + playSoundEffect(SoundEffectConstants.CLICK); + if (view != null) { + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); + } + mOnItemClickListener.onItemClick(/*this*/null, view, position, id); + return true; + } + + return false; + } + + /** + * Interface definition for a callback to be invoked when an item in this + * view has been clicked and held. + */ + public interface OnItemLongClickListener { + /** + * Callback method to be invoked when an item in this view has been + * clicked and held. + * + * Implementers can call getItemAtPosition(position) if they need to access + * the data associated with the selected item. + * + * @param parent The AbsListView where the click happened + * @param view The view within the AbsListView that was clicked + * @param position The position of the view in the list + * @param id The row id of the item that was clicked + * + * @return true if the callback consumed the long click, false otherwise + */ + boolean onItemLongClick(IcsAdapterView parent, View view, int position, long id); + } + + + /** + * Register a callback to be invoked when an item in this AdapterView has + * been clicked and held + * + * @param listener The callback that will run + */ + public void setOnItemLongClickListener(OnItemLongClickListener listener) { + if (!isLongClickable()) { + setLongClickable(true); + } + mOnItemLongClickListener = listener; + } + + /** + * @return The callback to be invoked with an item in this AdapterView has + * been clicked and held, or null id no callback as been set. + */ + public final OnItemLongClickListener getOnItemLongClickListener() { + return mOnItemLongClickListener; + } + + /** + * Interface definition for a callback to be invoked when + * an item in this view has been selected. + */ + public interface OnItemSelectedListener { + /** + *

Callback method to be invoked when an item in this view has been + * selected. This callback is invoked only when the newly selected + * position is different from the previously selected position or if + * there was no selected item.

+ * + * Impelmenters can call getItemAtPosition(position) if they need to access the + * data associated with the selected item. + * + * @param parent The AdapterView where the selection happened + * @param view The view within the AdapterView that was clicked + * @param position The position of the view in the adapter + * @param id The row id of the item that is selected + */ + void onItemSelected(IcsAdapterView parent, View view, int position, long id); + + /** + * Callback method to be invoked when the selection disappears from this + * view. The selection can disappear for instance when touch is activated + * or when the adapter becomes empty. + * + * @param parent The AdapterView that now contains no selected item. + */ + void onNothingSelected(IcsAdapterView parent); + } + + + /** + * Register a callback to be invoked when an item in this AdapterView has + * been selected. + * + * @param listener The callback that will run + */ + public void setOnItemSelectedListener(OnItemSelectedListener listener) { + mOnItemSelectedListener = listener; + } + + public final OnItemSelectedListener getOnItemSelectedListener() { + return mOnItemSelectedListener; + } + + /** + * Extra menu information provided to the + * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) } + * callback when a context menu is brought up for this AdapterView. + * + */ + public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo { + + public AdapterContextMenuInfo(View targetView, int position, long id) { + this.targetView = targetView; + this.position = position; + this.id = id; + } + + /** + * The child view for which the context menu is being displayed. This + * will be one of the children of this AdapterView. + */ + public View targetView; + + /** + * The position in the adapter for which the context menu is being + * displayed. + */ + public int position; + + /** + * The row id of the item for which the context menu is being displayed. + */ + public long id; + } + + /** + * Returns the adapter currently associated with this widget. + * + * @return The adapter used to provide this view's content. + */ + public abstract T getAdapter(); + + /** + * Sets the adapter that provides the data and the views to represent the data + * in this widget. + * + * @param adapter The adapter to use to create this view's content. + */ + public abstract void setAdapter(T adapter); + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @param child Ignored. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void addView(View child) { + throw new UnsupportedOperationException("addView(View) is not supported in AdapterView"); + } + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @param child Ignored. + * @param index Ignored. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void addView(View child, int index) { + throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView"); + } + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @param child Ignored. + * @param params Ignored. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void addView(View child, LayoutParams params) { + throw new UnsupportedOperationException("addView(View, LayoutParams) " + + "is not supported in AdapterView"); + } + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @param child Ignored. + * @param index Ignored. + * @param params Ignored. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void addView(View child, int index, LayoutParams params) { + throw new UnsupportedOperationException("addView(View, int, LayoutParams) " + + "is not supported in AdapterView"); + } + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @param child Ignored. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void removeView(View child) { + throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView"); + } + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @param index Ignored. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void removeViewAt(int index) { + throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView"); + } + + /** + * This method is not supported and throws an UnsupportedOperationException when called. + * + * @throws UnsupportedOperationException Every time this method is invoked. + */ + @Override + public void removeAllViews() { + throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView"); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + mLayoutHeight = getHeight(); + } + + /** + * Return the position of the currently selected item within the adapter's data set + * + * @return int Position (starting at 0), or {@link #INVALID_POSITION} if there is nothing selected. + */ + @ViewDebug.CapturedViewProperty + public int getSelectedItemPosition() { + return mNextSelectedPosition; + } + + /** + * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID} + * if nothing is selected. + */ + @ViewDebug.CapturedViewProperty + public long getSelectedItemId() { + return mNextSelectedRowId; + } + + /** + * @return The view corresponding to the currently selected item, or null + * if nothing is selected + */ + public abstract View getSelectedView(); + + /** + * @return The data corresponding to the currently selected item, or + * null if there is nothing selected. + */ + public Object getSelectedItem() { + T adapter = getAdapter(); + int selection = getSelectedItemPosition(); + if (adapter != null && adapter.getCount() > 0 && selection >= 0) { + return adapter.getItem(selection); + } else { + return null; + } + } + + /** + * @return The number of items owned by the Adapter associated with this + * AdapterView. (This is the number of data items, which may be + * larger than the number of visible views.) + */ + @ViewDebug.CapturedViewProperty + public int getCount() { + return mItemCount; + } + + /** + * Get the position within the adapter's data set for the view, where view is a an adapter item + * or a descendant of an adapter item. + * + * @param view an adapter item, or a descendant of an adapter item. This must be visible in this + * AdapterView at the time of the call. + * @return the position within the adapter's data set of the view, or {@link #INVALID_POSITION} + * if the view does not correspond to a list item (or it is not currently visible). + */ + public int getPositionForView(View view) { + View listItem = view; + try { + View v; + while (!(v = (View) listItem.getParent()).equals(this)) { + listItem = v; + } + } catch (ClassCastException e) { + // We made it up to the window without find this list view + return INVALID_POSITION; + } + + // Search the children for the list item + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + if (getChildAt(i).equals(listItem)) { + return mFirstPosition + i; + } + } + + // Child not found! + return INVALID_POSITION; + } + + /** + * Returns the position within the adapter's data set for the first item + * displayed on screen. + * + * @return The position within the adapter's data set + */ + public int getFirstVisiblePosition() { + return mFirstPosition; + } + + /** + * Returns the position within the adapter's data set for the last item + * displayed on screen. + * + * @return The position within the adapter's data set + */ + public int getLastVisiblePosition() { + return mFirstPosition + getChildCount() - 1; + } + + /** + * Sets the currently selected item. To support accessibility subclasses that + * override this method must invoke the overriden super method first. + * + * @param position Index (starting at 0) of the data item to be selected. + */ + public abstract void setSelection(int position); + + /** + * Sets the view to show if the adapter is empty + */ + public void setEmptyView(View emptyView) { + mEmptyView = emptyView; + + final T adapter = getAdapter(); + final boolean empty = ((adapter == null) || adapter.isEmpty()); + updateEmptyStatus(empty); + } + + /** + * When the current adapter is empty, the AdapterView can display a special view + * call the empty view. The empty view is used to provide feedback to the user + * that no data is available in this AdapterView. + * + * @return The view to show if the adapter is empty. + */ + public View getEmptyView() { + return mEmptyView; + } + + /** + * Indicates whether this view is in filter mode. Filter mode can for instance + * be enabled by a user when typing on the keyboard. + * + * @return True if the view is in filter mode, false otherwise. + */ + boolean isInFilterMode() { + return false; + } + + @Override + public void setFocusable(boolean focusable) { + final T adapter = getAdapter(); + final boolean empty = adapter == null || adapter.getCount() == 0; + + mDesiredFocusableState = focusable; + if (!focusable) { + mDesiredFocusableInTouchModeState = false; + } + + super.setFocusable(focusable && (!empty || isInFilterMode())); + } + + @Override + public void setFocusableInTouchMode(boolean focusable) { + final T adapter = getAdapter(); + final boolean empty = adapter == null || adapter.getCount() == 0; + + mDesiredFocusableInTouchModeState = focusable; + if (focusable) { + mDesiredFocusableState = true; + } + + super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode())); + } + + void checkFocus() { + final T adapter = getAdapter(); + final boolean empty = adapter == null || adapter.getCount() == 0; + final boolean focusable = !empty || isInFilterMode(); + // The order in which we set focusable in touch mode/focusable may matter + // for the client, see View.setFocusableInTouchMode() comments for more + // details + super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState); + super.setFocusable(focusable && mDesiredFocusableState); + if (mEmptyView != null) { + updateEmptyStatus((adapter == null) || adapter.isEmpty()); + } + } + + /** + * Update the status of the list based on the empty parameter. If empty is true and + * we have an empty view, display it. In all the other cases, make sure that the listview + * is VISIBLE and that the empty view is GONE (if it's not null). + */ + private void updateEmptyStatus(boolean empty) { + if (isInFilterMode()) { + empty = false; + } + + if (empty) { + if (mEmptyView != null) { + mEmptyView.setVisibility(View.VISIBLE); + setVisibility(View.GONE); + } else { + // If the caller just removed our empty view, make sure the list view is visible + setVisibility(View.VISIBLE); + } + + // We are now GONE, so pending layouts will not be dispatched. + // Force one here to make sure that the state of the list matches + // the state of the adapter. + if (mDataChanged) { + this.onLayout(false, getLeft(), getTop(), getRight(), getBottom()); + } + } else { + if (mEmptyView != null) mEmptyView.setVisibility(View.GONE); + setVisibility(View.VISIBLE); + } + } + + /** + * Gets the data associated with the specified position in the list. + * + * @param position Which data to get + * @return The data associated with the specified position in the list + */ + public Object getItemAtPosition(int position) { + T adapter = getAdapter(); + return (adapter == null || position < 0) ? null : adapter.getItem(position); + } + + public long getItemIdAtPosition(int position) { + T adapter = getAdapter(); + return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position); + } + + @Override + public void setOnClickListener(OnClickListener l) { + throw new RuntimeException("Don't call setOnClickListener for an AdapterView. " + + "You probably want setOnItemClickListener instead"); + } + + /** + * Override to prevent freezing of any views created by the adapter. + */ + @Override + protected void dispatchSaveInstanceState(SparseArray container) { + dispatchFreezeSelfOnly(container); + } + + /** + * Override to prevent thawing of any views created by the adapter. + */ + @Override + protected void dispatchRestoreInstanceState(SparseArray container) { + dispatchThawSelfOnly(container); + } + + class AdapterDataSetObserver extends DataSetObserver { + + private Parcelable mInstanceState = null; + + @Override + public void onChanged() { + mDataChanged = true; + mOldItemCount = mItemCount; + mItemCount = getAdapter().getCount(); + + // Detect the case where a cursor that was previously invalidated has + // been repopulated with new data. + if (IcsAdapterView.this.getAdapter().hasStableIds() && mInstanceState != null + && mOldItemCount == 0 && mItemCount > 0) { + IcsAdapterView.this.onRestoreInstanceState(mInstanceState); + mInstanceState = null; + } else { + rememberSyncState(); + } + checkFocus(); + requestLayout(); + } + + @Override + public void onInvalidated() { + mDataChanged = true; + + if (IcsAdapterView.this.getAdapter().hasStableIds()) { + // Remember the current state for the case where our hosting activity is being + // stopped and later restarted + mInstanceState = IcsAdapterView.this.onSaveInstanceState(); + } + + // Data is invalid so we should reset our state + mOldItemCount = mItemCount; + mItemCount = 0; + mSelectedPosition = INVALID_POSITION; + mSelectedRowId = INVALID_ROW_ID; + mNextSelectedPosition = INVALID_POSITION; + mNextSelectedRowId = INVALID_ROW_ID; + mNeedSync = false; + + checkFocus(); + requestLayout(); + } + + public void clearSavedState() { + mInstanceState = null; + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + removeCallbacks(mSelectionNotifier); + } + + private class SelectionNotifier implements Runnable { + public void run() { + if (mDataChanged) { + // Data has changed between when this SelectionNotifier + // was posted and now. We need to wait until the AdapterView + // has been synched to the new data. + if (getAdapter() != null) { + post(this); + } + } else { + fireOnSelected(); + } + } + } + + void selectionChanged() { + if (mOnItemSelectedListener != null) { + if (mInLayout || mBlockLayoutRequests) { + // If we are in a layout traversal, defer notification + // by posting. This ensures that the view tree is + // in a consistent state and is able to accomodate + // new layout or invalidate requests. + if (mSelectionNotifier == null) { + mSelectionNotifier = new SelectionNotifier(); + } + post(mSelectionNotifier); + } else { + fireOnSelected(); + } + } + + // we fire selection events here not in View + if (mSelectedPosition != ListView.INVALID_POSITION && isShown() && !isInTouchMode()) { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } + } + + private void fireOnSelected() { + if (mOnItemSelectedListener == null) + return; + + int selection = this.getSelectedItemPosition(); + if (selection >= 0) { + View v = getSelectedView(); + mOnItemSelectedListener.onItemSelected(this, v, selection, + getAdapter().getItemId(selection)); + } else { + mOnItemSelectedListener.onNothingSelected(this); + } + } + + @Override + public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { + View selectedView = getSelectedView(); + if (selectedView != null && selectedView.getVisibility() == VISIBLE + && selectedView.dispatchPopulateAccessibilityEvent(event)) { + return true; + } + return false; + } + + @Override + public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) { + if (super.onRequestSendAccessibilityEvent(child, event)) { + // Add a record for ourselves as well. + AccessibilityEvent record = AccessibilityEvent.obtain(); + onInitializeAccessibilityEvent(record); + // Populate with the text of the requesting child. + child.dispatchPopulateAccessibilityEvent(record); + event.appendRecord(record); + return true; + } + return false; + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setScrollable(isScrollableForAccessibility()); + View selectedView = getSelectedView(); + if (selectedView != null) { + info.setEnabled(selectedView.isEnabled()); + } + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setScrollable(isScrollableForAccessibility()); + View selectedView = getSelectedView(); + if (selectedView != null) { + event.setEnabled(selectedView.isEnabled()); + } + event.setCurrentItemIndex(getSelectedItemPosition()); + event.setFromIndex(getFirstVisiblePosition()); + event.setToIndex(getLastVisiblePosition()); + event.setItemCount(getCount()); + } + + private boolean isScrollableForAccessibility() { + T adapter = getAdapter(); + if (adapter != null) { + final int itemCount = adapter.getCount(); + return itemCount > 0 + && (getFirstVisiblePosition() > 0 || getLastVisiblePosition() < itemCount - 1); + } + return false; + } + + @Override + protected boolean canAnimate() { + return super.canAnimate() && mItemCount > 0; + } + + void handleDataChanged() { + final int count = mItemCount; + boolean found = false; + + if (count > 0) { + + int newPos; + + // Find the row we are supposed to sync to + if (mNeedSync) { + // Update this first, since setNextSelectedPositionInt inspects + // it + mNeedSync = false; + + // See if we can find a position in the new data with the same + // id as the old selection + newPos = findSyncPosition(); + if (newPos >= 0) { + // Verify that new selection is selectable + int selectablePos = lookForSelectablePosition(newPos, true); + if (selectablePos == newPos) { + // Same row id is selected + setNextSelectedPositionInt(newPos); + found = true; + } + } + } + if (!found) { + // Try to use the same position if we can't find matching data + newPos = getSelectedItemPosition(); + + // Pin position to the available range + if (newPos >= count) { + newPos = count - 1; + } + if (newPos < 0) { + newPos = 0; + } + + // Make sure we select something selectable -- first look down + int selectablePos = lookForSelectablePosition(newPos, true); + if (selectablePos < 0) { + // Looking down didn't work -- try looking up + selectablePos = lookForSelectablePosition(newPos, false); + } + if (selectablePos >= 0) { + setNextSelectedPositionInt(selectablePos); + checkSelectionChanged(); + found = true; + } + } + } + if (!found) { + // Nothing is selected + mSelectedPosition = INVALID_POSITION; + mSelectedRowId = INVALID_ROW_ID; + mNextSelectedPosition = INVALID_POSITION; + mNextSelectedRowId = INVALID_ROW_ID; + mNeedSync = false; + checkSelectionChanged(); + } + } + + void checkSelectionChanged() { + if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) { + selectionChanged(); + mOldSelectedPosition = mSelectedPosition; + mOldSelectedRowId = mSelectedRowId; + } + } + + /** + * Searches the adapter for a position matching mSyncRowId. The search starts at mSyncPosition + * and then alternates between moving up and moving down until 1) we find the right position, or + * 2) we run out of time, or 3) we have looked at every position + * + * @return Position of the row that matches mSyncRowId, or {@link #INVALID_POSITION} if it can't + * be found + */ + int findSyncPosition() { + int count = mItemCount; + + if (count == 0) { + return INVALID_POSITION; + } + + long idToMatch = mSyncRowId; + int seed = mSyncPosition; + + // If there isn't a selection don't hunt for it + if (idToMatch == INVALID_ROW_ID) { + return INVALID_POSITION; + } + + // Pin seed to reasonable values + seed = Math.max(0, seed); + seed = Math.min(count - 1, seed); + + long endTime = SystemClock.uptimeMillis() + SYNC_MAX_DURATION_MILLIS; + + long rowId; + + // first position scanned so far + int first = seed; + + // last position scanned so far + int last = seed; + + // True if we should move down on the next iteration + boolean next = false; + + // True when we have looked at the first item in the data + boolean hitFirst; + + // True when we have looked at the last item in the data + boolean hitLast; + + // Get the item ID locally (instead of getItemIdAtPosition), so + // we need the adapter + T adapter = getAdapter(); + if (adapter == null) { + return INVALID_POSITION; + } + + while (SystemClock.uptimeMillis() <= endTime) { + rowId = adapter.getItemId(seed); + if (rowId == idToMatch) { + // Found it! + return seed; + } + + hitLast = last == count - 1; + hitFirst = first == 0; + + if (hitLast && hitFirst) { + // Looked at everything + break; + } + + if (hitFirst || (next && !hitLast)) { + // Either we hit the top, or we are trying to move down + last++; + seed = last; + // Try going up next time + next = false; + } else if (hitLast || (!next && !hitFirst)) { + // Either we hit the bottom, or we are trying to move up + first--; + seed = first; + // Try going down next time + next = true; + } + + } + + return INVALID_POSITION; + } + + /** + * Find a position that can be selected (i.e., is not a separator). + * + * @param position The starting position to look at. + * @param lookDown Whether to look down for other positions. + * @return The next selectable position starting at position and then searching either up or + * down. Returns {@link #INVALID_POSITION} if nothing can be found. + */ + int lookForSelectablePosition(int position, boolean lookDown) { + return position; + } + + /** + * Utility to keep mSelectedPosition and mSelectedRowId in sync + * @param position Our current position + */ + void setSelectedPositionInt(int position) { + mSelectedPosition = position; + mSelectedRowId = getItemIdAtPosition(position); + } + + /** + * Utility to keep mNextSelectedPosition and mNextSelectedRowId in sync + * @param position Intended value for mSelectedPosition the next time we go + * through layout + */ + void setNextSelectedPositionInt(int position) { + mNextSelectedPosition = position; + mNextSelectedRowId = getItemIdAtPosition(position); + // If we are trying to sync to the selection, update that too + if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) { + mSyncPosition = position; + mSyncRowId = mNextSelectedRowId; + } + } + + /** + * Remember enough information to restore the screen state when the data has + * changed. + * + */ + void rememberSyncState() { + if (getChildCount() > 0) { + mNeedSync = true; + mSyncHeight = mLayoutHeight; + if (mSelectedPosition >= 0) { + // Sync the selection state + View v = getChildAt(mSelectedPosition - mFirstPosition); + mSyncRowId = mNextSelectedRowId; + mSyncPosition = mNextSelectedPosition; + if (v != null) { + mSpecificTop = v.getTop(); + } + mSyncMode = SYNC_SELECTED_POSITION; + } else { + // Sync the based on the offset of the first view + View v = getChildAt(0); + T adapter = getAdapter(); + if (mFirstPosition >= 0 && mFirstPosition < adapter.getCount()) { + mSyncRowId = adapter.getItemId(mFirstPosition); + } else { + mSyncRowId = NO_ID; + } + mSyncPosition = mFirstPosition; + if (v != null) { + mSpecificTop = v.getTop(); + } + mSyncMode = SYNC_FIRST_POSITION; + } + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java new file mode 100644 index 000000000..a78b3f71b --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsColorDrawable.java @@ -0,0 +1,41 @@ +package com.actionbarsherlock.internal.widget; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; + +/** + * A version of {@link android.graphics.drawable.ColorDrawable} that respects bounds. + */ +public class IcsColorDrawable extends Drawable { + private int color; + private final Paint paint = new Paint(); + + public IcsColorDrawable(int color) { + this.color = color; + } + + @Override public void draw(Canvas canvas) { + if ((color >>> 24) != 0) { + paint.setColor(color); + canvas.drawRect(getBounds(), paint); + } + } + + @Override + public void setAlpha(int alpha) { + if (alpha != (color >>> 24)) { + color = (color & 0x00FFFFFF) & (alpha << 24); + invalidateSelf(); + } + } + + @Override public void setColorFilter(ColorFilter colorFilter) { + //Ignored + } + + @Override public int getOpacity() { + return color >>> 24; + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java new file mode 100644 index 000000000..4947c41df --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsLinearLayout.java @@ -0,0 +1,410 @@ +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; + +import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout; + +/** + * A simple extension of a regular linear layout that supports the divider API + * of Android 4.0+. The dividers are added adjacent to the children by changing + * their layout params. If you need to rely on the margins which fall in the + * same orientation as the layout you should wrap the child in a simple + * {@link android.widget.FrameLayout} so it can receive the margin. + */ +public class IcsLinearLayout extends NineLinearLayout { + private static final int[] R_styleable_LinearLayout = new int[] { + /* 0 */ android.R.attr.divider, + /* 1 */ android.R.attr.measureWithLargestChild, + /* 2 */ android.R.attr.showDividers, + /* 3 */ android.R.attr.dividerPadding, + }; + private static final int LinearLayout_divider = 0; + private static final int LinearLayout_measureWithLargestChild = 1; + private static final int LinearLayout_showDividers = 2; + private static final int LinearLayout_dividerPadding = 3; + + /** + * Don't show any dividers. + */ + public static final int SHOW_DIVIDER_NONE = 0; + /** + * Show a divider at the beginning of the group. + */ + public static final int SHOW_DIVIDER_BEGINNING = 1; + /** + * Show dividers between each item in the group. + */ + public static final int SHOW_DIVIDER_MIDDLE = 2; + /** + * Show a divider at the end of the group. + */ + public static final int SHOW_DIVIDER_END = 4; + + + private Drawable mDivider; + private int mDividerWidth; + private int mDividerHeight; + private int mShowDividers; + private int mDividerPadding; + + private boolean mUseLargestChild; + + public IcsLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray a = context.obtainStyledAttributes(attrs, /*com.android.internal.R.styleable.*/R_styleable_LinearLayout); + + setDividerDrawable(a.getDrawable(/*com.android.internal.R.styleable.*/LinearLayout_divider)); + mShowDividers = a.getInt(/*com.android.internal.R.styleable.*/LinearLayout_showDividers, SHOW_DIVIDER_NONE); + mDividerPadding = a.getDimensionPixelSize(/*com.android.internal.R.styleable.*/LinearLayout_dividerPadding, 0); + mUseLargestChild = a.getBoolean(/*com.android.internal.R.styleable.*/LinearLayout_measureWithLargestChild, false); + + a.recycle(); + } + + /** + * Set how dividers should be shown between items in this layout + * + * @param showDividers One or more of {@link #SHOW_DIVIDER_BEGINNING}, + * {@link #SHOW_DIVIDER_MIDDLE}, or {@link #SHOW_DIVIDER_END}, + * or {@link #SHOW_DIVIDER_NONE} to show no dividers. + */ + public void setShowDividers(int showDividers) { + if (showDividers != mShowDividers) { + requestLayout(); + invalidate(); //XXX This is required if you are toggling a divider off + } + mShowDividers = showDividers; + } + + /** + * @return A flag set indicating how dividers should be shown around items. + * @see #setShowDividers(int) + */ + public int getShowDividers() { + return mShowDividers; + } + + /** + * Set a drawable to be used as a divider between items. + * @param divider Drawable that will divide each item. + * @see #setShowDividers(int) + */ + public void setDividerDrawable(Drawable divider) { + if (divider == mDivider) { + return; + } + mDivider = divider; + if (divider != null) { + mDividerWidth = divider.getIntrinsicWidth(); + mDividerHeight = divider.getIntrinsicHeight(); + } else { + mDividerWidth = 0; + mDividerHeight = 0; + } + setWillNotDraw(divider == null); + requestLayout(); + } + + /** + * Set padding displayed on both ends of dividers. + * + * @param padding Padding value in pixels that will be applied to each end + * + * @see #setShowDividers(int) + * @see #setDividerDrawable(Drawable) + * @see #getDividerPadding() + */ + public void setDividerPadding(int padding) { + mDividerPadding = padding; + } + + /** + * Get the padding size used to inset dividers in pixels + * + * @see #setShowDividers(int) + * @see #setDividerDrawable(Drawable) + * @see #setDividerPadding(int) + */ + public int getDividerPadding() { + return mDividerPadding; + } + + /** + * Get the width of the current divider drawable. + * + * @hide Used internally by framework. + */ + public int getDividerWidth() { + return mDividerWidth; + } + + @Override + protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { + final int index = indexOfChild(child); + final int orientation = getOrientation(); + final LayoutParams params = (LayoutParams) child.getLayoutParams(); + if (hasDividerBeforeChildAt(index)) { + if (orientation == VERTICAL) { + //Account for the divider by pushing everything up + params.topMargin = mDividerHeight; + } else { + //Account for the divider by pushing everything left + params.leftMargin = mDividerWidth; + } + } + + final int count = getChildCount(); + if (index == count - 1) { + if (hasDividerBeforeChildAt(count)) { + if (orientation == VERTICAL) { + params.bottomMargin = mDividerHeight; + } else { + params.rightMargin = mDividerWidth; + } + } + } + super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); + } + + @Override + protected void onDraw(Canvas canvas) { + if (mDivider != null) { + if (getOrientation() == VERTICAL) { + drawDividersVertical(canvas); + } else { + drawDividersHorizontal(canvas); + } + } + super.onDraw(canvas); + } + + void drawDividersVertical(Canvas canvas) { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + + if (child != null && child.getVisibility() != GONE) { + if (hasDividerBeforeChildAt(i)) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int top = child.getTop() - lp.topMargin/* - mDividerHeight*/; + drawHorizontalDivider(canvas, top); + } + } + } + + if (hasDividerBeforeChildAt(count)) { + final View child = getChildAt(count - 1); + int bottom = 0; + if (child == null) { + bottom = getHeight() - getPaddingBottom() - mDividerHeight; + } else { + //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + bottom = child.getBottom()/* + lp.bottomMargin*/; + } + drawHorizontalDivider(canvas, bottom); + } + } + + void drawDividersHorizontal(Canvas canvas) { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final View child = getChildAt(i); + + if (child != null && child.getVisibility() != GONE) { + if (hasDividerBeforeChildAt(i)) { + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + final int left = child.getLeft() - lp.leftMargin/* - mDividerWidth*/; + drawVerticalDivider(canvas, left); + } + } + } + + if (hasDividerBeforeChildAt(count)) { + final View child = getChildAt(count - 1); + int right = 0; + if (child == null) { + right = getWidth() - getPaddingRight() - mDividerWidth; + } else { + //final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + right = child.getRight()/* + lp.rightMargin*/; + } + drawVerticalDivider(canvas, right); + } + } + + void drawHorizontalDivider(Canvas canvas, int top) { + mDivider.setBounds(getPaddingLeft() + mDividerPadding, top, + getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight); + mDivider.draw(canvas); + } + + void drawVerticalDivider(Canvas canvas, int left) { + mDivider.setBounds(left, getPaddingTop() + mDividerPadding, + left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding); + mDivider.draw(canvas); + } + + /** + * Determines where to position dividers between children. + * + * @param childIndex Index of child to check for preceding divider + * @return true if there should be a divider before the child at childIndex + * @hide Pending API consideration. Currently only used internally by the system. + */ + protected boolean hasDividerBeforeChildAt(int childIndex) { + if (childIndex == 0) { + return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0; + } else if (childIndex == getChildCount()) { + return (mShowDividers & SHOW_DIVIDER_END) != 0; + } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) { + boolean hasVisibleViewBefore = false; + for (int i = childIndex - 1; i >= 0; i--) { + if (getChildAt(i).getVisibility() != GONE) { + hasVisibleViewBefore = true; + break; + } + } + return hasVisibleViewBefore; + } + return false; + } + + /** + * When true, all children with a weight will be considered having + * the minimum size of the largest child. If false, all children are + * measured normally. + * + * @return True to measure children with a weight using the minimum + * size of the largest child, false otherwise. + * + * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild + */ + public boolean isMeasureWithLargestChildEnabled() { + return mUseLargestChild; + } + + /** + * When set to true, all children with a weight will be considered having + * the minimum size of the largest child. If false, all children are + * measured normally. + * + * Disabled by default. + * + * @param enabled True to measure children with a weight using the + * minimum size of the largest child, false otherwise. + * + * @attr ref android.R.styleable#LinearLayout_measureWithLargestChild + */ + public void setMeasureWithLargestChildEnabled(boolean enabled) { + mUseLargestChild = enabled; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + if (mUseLargestChild) { + final int orientation = getOrientation(); + switch (orientation) { + case HORIZONTAL: + useLargestChildHorizontal(); + break; + + case VERTICAL: + useLargestChildVertical(); + break; + } + } + } + + private void useLargestChildHorizontal() { + final int childCount = getChildCount(); + + // Find largest child width + int largestChildWidth = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + largestChildWidth = Math.max(child.getMeasuredWidth(), largestChildWidth); + } + + int totalWidth = 0; + // Re-measure childs + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + float childExtra = lp.weight; + if (childExtra > 0) { + child.measure( + MeasureSpec.makeMeasureSpec(largestChildWidth, + MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), + MeasureSpec.EXACTLY)); + totalWidth += largestChildWidth; + + } else { + totalWidth += child.getMeasuredWidth(); + } + + totalWidth += lp.leftMargin + lp.rightMargin; + } + + totalWidth += getPaddingLeft() + getPaddingRight(); + setMeasuredDimension(totalWidth, getMeasuredHeight()); + } + + private void useLargestChildVertical() { + final int childCount = getChildCount(); + + // Find largest child width + int largestChildHeight = 0; + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + largestChildHeight = Math.max(child.getMeasuredHeight(), largestChildHeight); + } + + int totalHeight = 0; + // Re-measure childs + for (int i = 0; i < childCount; i++) { + final View child = getChildAt(i); + + if (child == null || child.getVisibility() == View.GONE) { + continue; + } + + final LinearLayout.LayoutParams lp = + (LinearLayout.LayoutParams) child.getLayoutParams(); + + float childExtra = lp.weight; + if (childExtra > 0) { + child.measure( + MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), + MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(largestChildHeight, + MeasureSpec.EXACTLY)); + totalHeight += largestChildHeight; + + } else { + totalHeight += child.getMeasuredHeight(); + } + + totalHeight += lp.leftMargin + lp.rightMargin; + } + + totalHeight += getPaddingLeft() + getPaddingRight(); + setMeasuredDimension(getMeasuredWidth(), totalHeight); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java new file mode 100644 index 000000000..d13c6cea9 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsListPopupWindow.java @@ -0,0 +1,644 @@ +package com.actionbarsherlock.internal.widget; + +import com.actionbarsherlock.R; + +import android.content.Context; +import android.content.res.Resources; +import android.database.DataSetObserver; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Handler; +import android.util.AttributeSet; +import android.view.ContextThemeWrapper; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.View.OnTouchListener; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.LinearLayout; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.PopupWindow; + +/** + * A proxy between pre- and post-Honeycomb implementations of this class. + */ +public class IcsListPopupWindow { + /** + * This value controls the length of time that the user + * must leave a pointer down without scrolling to expand + * the autocomplete dropdown list to cover the IME. + */ + private static final int EXPAND_LIST_TIMEOUT = 250; + + private Context mContext; + private PopupWindow mPopup; + private ListAdapter mAdapter; + private DropDownListView mDropDownList; + + private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT; + private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT; + private int mDropDownHorizontalOffset; + private int mDropDownVerticalOffset; + private boolean mDropDownVerticalOffsetSet; + + private int mListItemExpandMaximum = Integer.MAX_VALUE; + + private View mPromptView; + private int mPromptPosition = POSITION_PROMPT_ABOVE; + + private DataSetObserver mObserver; + + private View mDropDownAnchorView; + + private Drawable mDropDownListHighlight; + + private AdapterView.OnItemClickListener mItemClickListener; + private AdapterView.OnItemSelectedListener mItemSelectedListener; + + private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable(); + private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor(); + private final PopupScrollListener mScrollListener = new PopupScrollListener(); + private final ListSelectorHider mHideSelector = new ListSelectorHider(); + + private Handler mHandler = new Handler(); + + private Rect mTempRect = new Rect(); + + private boolean mModal; + + public static final int POSITION_PROMPT_ABOVE = 0; + public static final int POSITION_PROMPT_BELOW = 1; + + public IcsListPopupWindow(Context context) { + this(context, null, R.attr.listPopupWindowStyle); + } + + public IcsListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) { + mContext = context; + mPopup = new PopupWindow(context, attrs, defStyleAttr); + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); + } + + public IcsListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + mContext = context; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + Context wrapped = new ContextThemeWrapper(context, defStyleRes); + mPopup = new PopupWindow(wrapped, attrs, defStyleAttr); + } else { + mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes); + } + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); + } + + public void setAdapter(ListAdapter adapter) { + if (mObserver == null) { + mObserver = new PopupDataSetObserver(); + } else if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(mObserver); + } + mAdapter = adapter; + if (mAdapter != null) { + adapter.registerDataSetObserver(mObserver); + } + + if (mDropDownList != null) { + mDropDownList.setAdapter(mAdapter); + } + } + + public void setPromptPosition(int position) { + mPromptPosition = position; + } + + public void setModal(boolean modal) { + mModal = true; + mPopup.setFocusable(modal); + } + + public void setBackgroundDrawable(Drawable d) { + mPopup.setBackgroundDrawable(d); + } + + public void setAnchorView(View anchor) { + mDropDownAnchorView = anchor; + } + + public void setHorizontalOffset(int offset) { + mDropDownHorizontalOffset = offset; + } + + public void setVerticalOffset(int offset) { + mDropDownVerticalOffset = offset; + mDropDownVerticalOffsetSet = true; + } + + public void setContentWidth(int width) { + Drawable popupBackground = mPopup.getBackground(); + if (popupBackground != null) { + popupBackground.getPadding(mTempRect); + mDropDownWidth = mTempRect.left + mTempRect.right + width; + } else { + mDropDownWidth = width; + } + } + + public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) { + mItemClickListener = clickListener; + } + + public void show() { + int height = buildDropDown(); + + int widthSpec = 0; + int heightSpec = 0; + + boolean noInputMethod = isInputMethodNotNeeded(); + //XXX mPopup.setAllowScrollingAnchorParent(!noInputMethod); + + if (mPopup.isShowing()) { + if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { + // The call to PopupWindow's update method below can accept -1 for any + // value you do not want to update. + widthSpec = -1; + } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { + widthSpec = mDropDownAnchorView.getWidth(); + } else { + widthSpec = mDropDownWidth; + } + + if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + // The call to PopupWindow's update method below can accept -1 for any + // value you do not want to update. + heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT; + if (noInputMethod) { + mPopup.setWindowLayoutMode( + mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? + ViewGroup.LayoutParams.MATCH_PARENT : 0, 0); + } else { + mPopup.setWindowLayoutMode( + mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? + ViewGroup.LayoutParams.MATCH_PARENT : 0, + ViewGroup.LayoutParams.MATCH_PARENT); + } + } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { + heightSpec = height; + } else { + heightSpec = mDropDownHeight; + } + + mPopup.setOutsideTouchable(true); + + mPopup.update(mDropDownAnchorView, mDropDownHorizontalOffset, + mDropDownVerticalOffset, widthSpec, heightSpec); + } else { + if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { + widthSpec = ViewGroup.LayoutParams.MATCH_PARENT; + } else { + if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { + mPopup.setWidth(mDropDownAnchorView.getWidth()); + } else { + mPopup.setWidth(mDropDownWidth); + } + } + + if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + heightSpec = ViewGroup.LayoutParams.MATCH_PARENT; + } else { + if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { + mPopup.setHeight(height); + } else { + mPopup.setHeight(mDropDownHeight); + } + } + + mPopup.setWindowLayoutMode(widthSpec, heightSpec); + //XXX mPopup.setClipToScreenEnabled(true); + + // use outside touchable to dismiss drop down when touching outside of it, so + // only set this if the dropdown is not always visible + mPopup.setOutsideTouchable(true); + mPopup.setTouchInterceptor(mTouchInterceptor); + mPopup.showAsDropDown(mDropDownAnchorView, + mDropDownHorizontalOffset, mDropDownVerticalOffset); + mDropDownList.setSelection(ListView.INVALID_POSITION); + + if (!mModal || mDropDownList.isInTouchMode()) { + clearListSelection(); + } + if (!mModal) { + mHandler.post(mHideSelector); + } + } + } + + public void dismiss() { + mPopup.dismiss(); + if (mPromptView != null) { + final ViewParent parent = mPromptView.getParent(); + if (parent instanceof ViewGroup) { + final ViewGroup group = (ViewGroup) parent; + group.removeView(mPromptView); + } + } + mPopup.setContentView(null); + mDropDownList = null; + mHandler.removeCallbacks(mResizePopupRunnable); + } + + public void setOnDismissListener(PopupWindow.OnDismissListener listener) { + mPopup.setOnDismissListener(listener); + } + + public void setInputMethodMode(int mode) { + mPopup.setInputMethodMode(mode); + } + + public void clearListSelection() { + final DropDownListView list = mDropDownList; + if (list != null) { + // WARNING: Please read the comment where mListSelectionHidden is declared + list.mListSelectionHidden = true; + //XXX list.hideSelector(); + list.requestLayout(); + } + } + + public boolean isShowing() { + return mPopup.isShowing(); + } + + private boolean isInputMethodNotNeeded() { + return mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; + } + + public ListView getListView() { + return mDropDownList; + } + + private int buildDropDown() { + ViewGroup dropDownView; + int otherHeights = 0; + + if (mDropDownList == null) { + Context context = mContext; + + mDropDownList = new DropDownListView(context, !mModal); + if (mDropDownListHighlight != null) { + mDropDownList.setSelector(mDropDownListHighlight); + } + mDropDownList.setAdapter(mAdapter); + mDropDownList.setOnItemClickListener(mItemClickListener); + mDropDownList.setFocusable(true); + mDropDownList.setFocusableInTouchMode(true); + mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, + int position, long id) { + + if (position != -1) { + DropDownListView dropDownList = mDropDownList; + + if (dropDownList != null) { + dropDownList.mListSelectionHidden = false; + } + } + } + + public void onNothingSelected(AdapterView parent) { + } + }); + mDropDownList.setOnScrollListener(mScrollListener); + + if (mItemSelectedListener != null) { + mDropDownList.setOnItemSelectedListener(mItemSelectedListener); + } + + dropDownView = mDropDownList; + + View hintView = mPromptView; + if (hintView != null) { + // if an hint has been specified, we accomodate more space for it and + // add a text view in the drop down menu, at the bottom of the list + LinearLayout hintContainer = new LinearLayout(context); + hintContainer.setOrientation(LinearLayout.VERTICAL); + + LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f + ); + + switch (mPromptPosition) { + case POSITION_PROMPT_BELOW: + hintContainer.addView(dropDownView, hintParams); + hintContainer.addView(hintView); + break; + + case POSITION_PROMPT_ABOVE: + hintContainer.addView(hintView); + hintContainer.addView(dropDownView, hintParams); + break; + + default: + break; + } + + // measure the hint's height to find how much more vertical space + // we need to add to the drop down's height + int widthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.AT_MOST); + int heightSpec = MeasureSpec.UNSPECIFIED; + hintView.measure(widthSpec, heightSpec); + + hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams(); + otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin + + hintParams.bottomMargin; + + dropDownView = hintContainer; + } + + mPopup.setContentView(dropDownView); + } else { + dropDownView = (ViewGroup) mPopup.getContentView(); + final View view = mPromptView; + if (view != null) { + LinearLayout.LayoutParams hintParams = + (LinearLayout.LayoutParams) view.getLayoutParams(); + otherHeights = view.getMeasuredHeight() + hintParams.topMargin + + hintParams.bottomMargin; + } + } + + // getMaxAvailableHeight() subtracts the padding, so we put it back + // to get the available height for the whole window + int padding = 0; + Drawable background = mPopup.getBackground(); + if (background != null) { + background.getPadding(mTempRect); + padding = mTempRect.top + mTempRect.bottom; + + // If we don't have an explicit vertical offset, determine one from the window + // background so that content will line up. + if (!mDropDownVerticalOffsetSet) { + mDropDownVerticalOffset = -mTempRect.top; + } + } + + // Max height available on the screen for a popup. + boolean ignoreBottomDecorations = + mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; + final int maxHeight = /*mPopup.*/getMaxAvailableHeight( + mDropDownAnchorView, mDropDownVerticalOffset, ignoreBottomDecorations); + + if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + return maxHeight + padding; + } + + final int listContent = /*mDropDownList.*/measureHeightOfChildren(MeasureSpec.UNSPECIFIED, + 0, -1/*ListView.NO_POSITION*/, maxHeight - otherHeights, -1); + // add padding only if the list has items in it, that way we don't show + // the popup if it is not needed + if (listContent > 0) otherHeights += padding; + + return listContent + otherHeights; + } + + private int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) { + final Rect displayFrame = new Rect(); + anchor.getWindowVisibleDisplayFrame(displayFrame); + + final int[] anchorPos = new int[2]; + anchor.getLocationOnScreen(anchorPos); + + int bottomEdge = displayFrame.bottom; + if (ignoreBottomDecorations) { + Resources res = anchor.getContext().getResources(); + bottomEdge = res.getDisplayMetrics().heightPixels; + } + final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset; + final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset; + + // anchorPos[1] is distance from anchor to top of screen + int returnedHeight = Math.max(distanceToBottom, distanceToTop); + if (mPopup.getBackground() != null) { + mPopup.getBackground().getPadding(mTempRect); + returnedHeight -= mTempRect.top + mTempRect.bottom; + } + + return returnedHeight; + } + + private int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, + final int maxHeight, int disallowPartialChildPosition) { + + final ListAdapter adapter = mAdapter; + if (adapter == null) { + return mDropDownList.getListPaddingTop() + mDropDownList.getListPaddingBottom(); + } + + // Include the padding of the list + int returnedHeight = mDropDownList.getListPaddingTop() + mDropDownList.getListPaddingBottom(); + final int dividerHeight = ((mDropDownList.getDividerHeight() > 0) && mDropDownList.getDivider() != null) ? mDropDownList.getDividerHeight() : 0; + // The previous height value that was less than maxHeight and contained + // no partial children + int prevHeightWithoutPartialChild = 0; + int i; + View child; + + // mItemCount - 1 since endPosition parameter is inclusive + endPosition = (endPosition == -1/*NO_POSITION*/) ? adapter.getCount() - 1 : endPosition; + + for (i = startPosition; i <= endPosition; ++i) { + child = mAdapter.getView(i, null, mDropDownList); + if (mDropDownList.getCacheColorHint() != 0) { + child.setDrawingCacheBackgroundColor(mDropDownList.getCacheColorHint()); + } + + measureScrapChild(child, i, widthMeasureSpec); + + if (i > 0) { + // Count the divider for all but one child + returnedHeight += dividerHeight; + } + + returnedHeight += child.getMeasuredHeight(); + + if (returnedHeight >= maxHeight) { + // We went over, figure out which height to return. If returnedHeight > maxHeight, + // then the i'th position did not fit completely. + return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) + && (i > disallowPartialChildPosition) // We've past the min pos + && (prevHeightWithoutPartialChild > 0) // We have a prev height + && (returnedHeight != maxHeight) // i'th child did not fit completely + ? prevHeightWithoutPartialChild + : maxHeight; + } + + if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { + prevHeightWithoutPartialChild = returnedHeight; + } + } + + // At this point, we went through the range of children, and they each + // completely fit, so return the returnedHeight + return returnedHeight; + } + private void measureScrapChild(View child, int position, int widthMeasureSpec) { + ListView.LayoutParams p = (ListView.LayoutParams) child.getLayoutParams(); + if (p == null) { + p = new ListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT, 0); + child.setLayoutParams(p); + } + //XXX p.viewType = mAdapter.getItemViewType(position); + //XXX p.forceAdd = true; + + int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec, + mDropDownList.getPaddingLeft() + mDropDownList.getPaddingRight(), p.width); + int lpHeight = p.height; + int childHeightSpec; + if (lpHeight > 0) { + childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); + } else { + childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + } + child.measure(childWidthSpec, childHeightSpec); + } + + private static class DropDownListView extends ListView { + /* + * WARNING: This is a workaround for a touch mode issue. + * + * Touch mode is propagated lazily to windows. This causes problems in + * the following scenario: + * - Type something in the AutoCompleteTextView and get some results + * - Move down with the d-pad to select an item in the list + * - Move up with the d-pad until the selection disappears + * - Type more text in the AutoCompleteTextView *using the soft keyboard* + * and get new results; you are now in touch mode + * - The selection comes back on the first item in the list, even though + * the list is supposed to be in touch mode + * + * Using the soft keyboard triggers the touch mode change but that change + * is propagated to our window only after the first list layout, therefore + * after the list attempts to resurrect the selection. + * + * The trick to work around this issue is to pretend the list is in touch + * mode when we know that the selection should not appear, that is when + * we know the user moved the selection away from the list. + * + * This boolean is set to true whenever we explicitly hide the list's + * selection and reset to false whenever we know the user moved the + * selection back to the list. + * + * When this boolean is true, isInTouchMode() returns true, otherwise it + * returns super.isInTouchMode(). + */ + private boolean mListSelectionHidden; + + private boolean mHijackFocus; + + public DropDownListView(Context context, boolean hijackFocus) { + super(context, null, /*com.android.internal.*/R.attr.dropDownListViewStyle); + mHijackFocus = hijackFocus; + // TODO: Add an API to control this + setCacheColorHint(0); // Transparent, since the background drawable could be anything. + } + + //XXX @Override + //View obtainView(int position, boolean[] isScrap) { + // View view = super.obtainView(position, isScrap); + + // if (view instanceof TextView) { + // ((TextView) view).setHorizontallyScrolling(true); + // } + + // return view; + //} + + @Override + public boolean isInTouchMode() { + // WARNING: Please read the comment where mListSelectionHidden is declared + return (mHijackFocus && mListSelectionHidden) || super.isInTouchMode(); + } + + @Override + public boolean hasWindowFocus() { + return mHijackFocus || super.hasWindowFocus(); + } + + @Override + public boolean isFocused() { + return mHijackFocus || super.isFocused(); + } + + @Override + public boolean hasFocus() { + return mHijackFocus || super.hasFocus(); + } + } + + private class PopupDataSetObserver extends DataSetObserver { + @Override + public void onChanged() { + if (isShowing()) { + // Resize the popup to fit new content + show(); + } + } + + @Override + public void onInvalidated() { + dismiss(); + } + } + + private class ListSelectorHider implements Runnable { + public void run() { + clearListSelection(); + } + } + + private class ResizePopupRunnable implements Runnable { + public void run() { + if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() && + mDropDownList.getChildCount() <= mListItemExpandMaximum) { + mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); + show(); + } + } + } + + private class PopupTouchInterceptor implements OnTouchListener { + public boolean onTouch(View v, MotionEvent event) { + final int action = event.getAction(); + final int x = (int) event.getX(); + final int y = (int) event.getY(); + + if (action == MotionEvent.ACTION_DOWN && + mPopup != null && mPopup.isShowing() && + (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) { + mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT); + } else if (action == MotionEvent.ACTION_UP) { + mHandler.removeCallbacks(mResizePopupRunnable); + } + return false; + } + } + + private class PopupScrollListener implements ListView.OnScrollListener { + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, + int totalItemCount) { + + } + + public void onScrollStateChanged(AbsListView view, int scrollState) { + if (scrollState == SCROLL_STATE_TOUCH_SCROLL && + !isInputMethodNotNeeded() && mPopup.getContentView() != null) { + mHandler.removeCallbacks(mResizePopupRunnable); + mResizePopupRunnable.run(); + } + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java new file mode 100644 index 000000000..1c02d4aca --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsProgressBar.java @@ -0,0 +1,1193 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.Shader; +import android.graphics.drawable.Animatable; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.graphics.drawable.shapes.Shape; +import android.os.Build; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewDebug; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; +import android.view.animation.LinearInterpolator; +import android.view.animation.Transformation; +import android.widget.RemoteViews.RemoteView; + + +/** + *

+ * Visual indicator of progress in some operation. Displays a bar to the user + * representing how far the operation has progressed; the application can + * change the amount of progress (modifying the length of the bar) as it moves + * forward. There is also a secondary progress displayable on a progress bar + * which is useful for displaying intermediate progress, such as the buffer + * level during a streaming playback progress bar. + *

+ * + *

+ * A progress bar can also be made indeterminate. In indeterminate mode, the + * progress bar shows a cyclic animation without an indication of progress. This mode is used by + * applications when the length of the task is unknown. The indeterminate progress bar can be either + * a spinning wheel or a horizontal bar. + *

+ * + *

The following code example shows how a progress bar can be used from + * a worker thread to update the user interface to notify the user of progress: + *

+ * + *
+ * public class MyActivity extends Activity {
+ *     private static final int PROGRESS = 0x1;
+ *
+ *     private ProgressBar mProgress;
+ *     private int mProgressStatus = 0;
+ *
+ *     private Handler mHandler = new Handler();
+ *
+ *     protected void onCreate(Bundle icicle) {
+ *         super.onCreate(icicle);
+ *
+ *         setContentView(R.layout.progressbar_activity);
+ *
+ *         mProgress = (ProgressBar) findViewById(R.id.progress_bar);
+ *
+ *         // Start lengthy operation in a background thread
+ *         new Thread(new Runnable() {
+ *             public void run() {
+ *                 while (mProgressStatus < 100) {
+ *                     mProgressStatus = doWork();
+ *
+ *                     // Update the progress bar
+ *                     mHandler.post(new Runnable() {
+ *                         public void run() {
+ *                             mProgress.setProgress(mProgressStatus);
+ *                         }
+ *                     });
+ *                 }
+ *             }
+ *         }).start();
+ *     }
+ * }
+ * + *

To add a progress bar to a layout file, you can use the {@code <ProgressBar>} element. + * By default, the progress bar is a spinning wheel (an indeterminate indicator). To change to a + * horizontal progress bar, apply the {@link android.R.style#Widget_ProgressBar_Horizontal + * Widget.ProgressBar.Horizontal} style, like so:

+ * + *
+ * <ProgressBar
+ *     style="@android:style/Widget.ProgressBar.Horizontal"
+ *     ... />
+ * + *

If you will use the progress bar to show real progress, you must use the horizontal bar. You + * can then increment the progress with {@link #incrementProgressBy incrementProgressBy()} or + * {@link #setProgress setProgress()}. By default, the progress bar is full when it reaches 100. If + * necessary, you can adjust the maximum value (the value for a full bar) using the {@link + * android.R.styleable#ProgressBar_max android:max} attribute. Other attributes available are listed + * below.

+ * + *

Another common style to apply to the progress bar is {@link + * android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}, which shows a smaller + * version of the spinning wheel—useful when waiting for content to load. + * For example, you can insert this kind of progress bar into your default layout for + * a view that will be populated by some content fetched from the Internet—the spinning wheel + * appears immediately and when your application receives the content, it replaces the progress bar + * with the loaded content. For example:

+ * + *
+ * <LinearLayout
+ *     android:orientation="horizontal"
+ *     ... >
+ *     <ProgressBar
+ *         android:layout_width="wrap_content"
+ *         android:layout_height="wrap_content"
+ *         style="@android:style/Widget.ProgressBar.Small"
+ *         android:layout_marginRight="5dp" />
+ *     <TextView
+ *         android:layout_width="wrap_content"
+ *         android:layout_height="wrap_content"
+ *         android:text="@string/loading" />
+ * </LinearLayout>
+ * + *

Other progress bar styles provided by the system include:

+ *
    + *
  • {@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal}
  • + *
  • {@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}
  • + *
  • {@link android.R.style#Widget_ProgressBar_Large Widget.ProgressBar.Large}
  • + *
  • {@link android.R.style#Widget_ProgressBar_Inverse Widget.ProgressBar.Inverse}
  • + *
  • {@link android.R.style#Widget_ProgressBar_Small_Inverse + * Widget.ProgressBar.Small.Inverse}
  • + *
  • {@link android.R.style#Widget_ProgressBar_Large_Inverse + * Widget.ProgressBar.Large.Inverse}
  • + *
+ *

The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary + * if your application uses a light colored theme (a white background).

+ * + *

XML attributes + *

+ * See {@link android.R.styleable#ProgressBar ProgressBar Attributes}, + * {@link android.R.styleable#View View Attributes} + *

+ * + * @attr ref android.R.styleable#ProgressBar_animationResolution + * @attr ref android.R.styleable#ProgressBar_indeterminate + * @attr ref android.R.styleable#ProgressBar_indeterminateBehavior + * @attr ref android.R.styleable#ProgressBar_indeterminateDrawable + * @attr ref android.R.styleable#ProgressBar_indeterminateDuration + * @attr ref android.R.styleable#ProgressBar_indeterminateOnly + * @attr ref android.R.styleable#ProgressBar_interpolator + * @attr ref android.R.styleable#ProgressBar_max + * @attr ref android.R.styleable#ProgressBar_maxHeight + * @attr ref android.R.styleable#ProgressBar_maxWidth + * @attr ref android.R.styleable#ProgressBar_minHeight + * @attr ref android.R.styleable#ProgressBar_minWidth + * @attr ref android.R.styleable#ProgressBar_progress + * @attr ref android.R.styleable#ProgressBar_progressDrawable + * @attr ref android.R.styleable#ProgressBar_secondaryProgress + */ +@RemoteView +public class IcsProgressBar extends View { + private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + private static final int MAX_LEVEL = 10000; + private static final int ANIMATION_RESOLUTION = 200; + private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200; + + private static final int[] ProgressBar = new int[] { + android.R.attr.maxWidth, + android.R.attr.maxHeight, + android.R.attr.max, + android.R.attr.progress, + android.R.attr.secondaryProgress, + android.R.attr.indeterminate, + android.R.attr.indeterminateOnly, + android.R.attr.indeterminateDrawable, + android.R.attr.progressDrawable, + android.R.attr.indeterminateDuration, + android.R.attr.indeterminateBehavior, + android.R.attr.minWidth, + android.R.attr.minHeight, + android.R.attr.interpolator, + android.R.attr.animationResolution, + }; + private static final int ProgressBar_maxWidth = 0; + private static final int ProgressBar_maxHeight = 1; + private static final int ProgressBar_max = 2; + private static final int ProgressBar_progress = 3; + private static final int ProgressBar_secondaryProgress = 4; + private static final int ProgressBar_indeterminate = 5; + private static final int ProgressBar_indeterminateOnly = 6; + private static final int ProgressBar_indeterminateDrawable = 7; + private static final int ProgressBar_progressDrawable = 8; + private static final int ProgressBar_indeterminateDuration = 9; + private static final int ProgressBar_indeterminateBehavior = 10; + private static final int ProgressBar_minWidth = 11; + private static final int ProgressBar_minHeight = 12; + private static final int ProgressBar_interpolator = 13; + private static final int ProgressBar_animationResolution = 14; + + int mMinWidth; + int mMaxWidth; + int mMinHeight; + int mMaxHeight; + + private int mProgress; + private int mSecondaryProgress; + private int mMax; + + private int mBehavior; + private int mDuration; + private boolean mIndeterminate; + private boolean mOnlyIndeterminate; + private Transformation mTransformation; + private AlphaAnimation mAnimation; + private Drawable mIndeterminateDrawable; + private int mIndeterminateRealLeft; + private int mIndeterminateRealTop; + private Drawable mProgressDrawable; + private Drawable mCurrentDrawable; + Bitmap mSampleTile; + private boolean mNoInvalidate; + private Interpolator mInterpolator; + private RefreshProgressRunnable mRefreshProgressRunnable; + private long mUiThreadId; + private boolean mShouldStartAnimationDrawable; + private long mLastDrawTime; + + private boolean mInDrawing; + + private int mAnimationResolution; + + private AccessibilityManager mAccessibilityManager; + private AccessibilityEventSender mAccessibilityEventSender; + + /** + * Create a new progress bar with range 0...100 and initial progress of 0. + * @param context the application environment + */ + public IcsProgressBar(Context context) { + this(context, null); + } + + public IcsProgressBar(Context context, AttributeSet attrs) { + this(context, attrs, android.R.attr.progressBarStyle); + } + + public IcsProgressBar(Context context, AttributeSet attrs, int defStyle) { + this(context, attrs, defStyle, 0); + } + + /** + * @hide + */ + public IcsProgressBar(Context context, AttributeSet attrs, int defStyle, int styleRes) { + super(context, attrs, defStyle); + mUiThreadId = Thread.currentThread().getId(); + initProgressBar(); + + TypedArray a = + context.obtainStyledAttributes(attrs, /*R.styleable.*/ProgressBar, defStyle, styleRes); + + mNoInvalidate = true; + + Drawable drawable = a.getDrawable(/*R.styleable.*/ProgressBar_progressDrawable); + if (drawable != null) { + drawable = tileify(drawable, false); + // Calling this method can set mMaxHeight, make sure the corresponding + // XML attribute for mMaxHeight is read after calling this method + setProgressDrawable(drawable); + } + + + mDuration = a.getInt(/*R.styleable.*/ProgressBar_indeterminateDuration, mDuration); + + mMinWidth = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_minWidth, mMinWidth); + mMaxWidth = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_maxWidth, mMaxWidth); + mMinHeight = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_minHeight, mMinHeight); + mMaxHeight = a.getDimensionPixelSize(/*R.styleable.*/ProgressBar_maxHeight, mMaxHeight); + + mBehavior = a.getInt(/*R.styleable.*/ProgressBar_indeterminateBehavior, mBehavior); + + final int resID = a.getResourceId( + /*com.android.internal.R.styleable.*/ProgressBar_interpolator, + android.R.anim.linear_interpolator); // default to linear interpolator + if (resID > 0) { + setInterpolator(context, resID); + } + + setMax(a.getInt(/*R.styleable.*/ProgressBar_max, mMax)); + + setProgress(a.getInt(/*R.styleable.*/ProgressBar_progress, mProgress)); + + setSecondaryProgress( + a.getInt(/*R.styleable.*/ProgressBar_secondaryProgress, mSecondaryProgress)); + + drawable = a.getDrawable(/*R.styleable.*/ProgressBar_indeterminateDrawable); + if (drawable != null) { + drawable = tileifyIndeterminate(drawable); + setIndeterminateDrawable(drawable); + } + + mOnlyIndeterminate = a.getBoolean( + /*R.styleable.*/ProgressBar_indeterminateOnly, mOnlyIndeterminate); + + mNoInvalidate = false; + + setIndeterminate(mOnlyIndeterminate || a.getBoolean( + /*R.styleable.*/ProgressBar_indeterminate, mIndeterminate)); + + mAnimationResolution = a.getInteger(/*R.styleable.*/ProgressBar_animationResolution, + ANIMATION_RESOLUTION); + + a.recycle(); + + mAccessibilityManager = (AccessibilityManager)context.getSystemService(Context.ACCESSIBILITY_SERVICE); + } + + /** + * Converts a drawable to a tiled version of itself. It will recursively + * traverse layer and state list drawables. + */ + private Drawable tileify(Drawable drawable, boolean clip) { + + if (drawable instanceof LayerDrawable) { + LayerDrawable background = (LayerDrawable) drawable; + final int N = background.getNumberOfLayers(); + Drawable[] outDrawables = new Drawable[N]; + + for (int i = 0; i < N; i++) { + int id = background.getId(i); + outDrawables[i] = tileify(background.getDrawable(i), + (id == android.R.id.progress || id == android.R.id.secondaryProgress)); + } + + LayerDrawable newBg = new LayerDrawable(outDrawables); + + for (int i = 0; i < N; i++) { + newBg.setId(i, background.getId(i)); + } + + return newBg; + + }/* else if (drawable instanceof StateListDrawable) { + StateListDrawable in = (StateListDrawable) drawable; + StateListDrawable out = new StateListDrawable(); + int numStates = in.getStateCount(); + for (int i = 0; i < numStates; i++) { + out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip)); + } + return out; + + }*/ else if (drawable instanceof BitmapDrawable) { + final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap(); + if (mSampleTile == null) { + mSampleTile = tileBitmap; + } + + final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); + + final BitmapShader bitmapShader = new BitmapShader(tileBitmap, + Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); + shapeDrawable.getPaint().setShader(bitmapShader); + + return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT, + ClipDrawable.HORIZONTAL) : shapeDrawable; + } + + return drawable; + } + + Shape getDrawableShape() { + final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 }; + return new RoundRectShape(roundedCorners, null, null); + } + + /** + * Convert a AnimationDrawable for use as a barberpole animation. + * Each frame of the animation is wrapped in a ClipDrawable and + * given a tiling BitmapShader. + */ + private Drawable tileifyIndeterminate(Drawable drawable) { + if (drawable instanceof AnimationDrawable) { + AnimationDrawable background = (AnimationDrawable) drawable; + final int N = background.getNumberOfFrames(); + AnimationDrawable newBg = new AnimationDrawable(); + newBg.setOneShot(background.isOneShot()); + + for (int i = 0; i < N; i++) { + Drawable frame = tileify(background.getFrame(i), true); + frame.setLevel(10000); + newBg.addFrame(frame, background.getDuration(i)); + } + newBg.setLevel(10000); + drawable = newBg; + } + return drawable; + } + + /** + *

+ * Initialize the progress bar's default values: + *

+ *
    + *
  • progress = 0
  • + *
  • max = 100
  • + *
  • animation duration = 4000 ms
  • + *
  • indeterminate = false
  • + *
  • behavior = repeat
  • + *
+ */ + private void initProgressBar() { + mMax = 100; + mProgress = 0; + mSecondaryProgress = 0; + mIndeterminate = false; + mOnlyIndeterminate = false; + mDuration = 4000; + mBehavior = AlphaAnimation.RESTART; + mMinWidth = 24; + mMaxWidth = 48; + mMinHeight = 24; + mMaxHeight = 48; + } + + /** + *

Indicate whether this progress bar is in indeterminate mode.

+ * + * @return true if the progress bar is in indeterminate mode + */ + @ViewDebug.ExportedProperty(category = "progress") + public synchronized boolean isIndeterminate() { + return mIndeterminate; + } + + /** + *

Change the indeterminate mode for this progress bar. In indeterminate + * mode, the progress is ignored and the progress bar shows an infinite + * animation instead.

+ * + * If this progress bar's style only supports indeterminate mode (such as the circular + * progress bars), then this will be ignored. + * + * @param indeterminate true to enable the indeterminate mode + */ + public synchronized void setIndeterminate(boolean indeterminate) { + if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) { + mIndeterminate = indeterminate; + + if (indeterminate) { + // swap between indeterminate and regular backgrounds + mCurrentDrawable = mIndeterminateDrawable; + startAnimation(); + } else { + mCurrentDrawable = mProgressDrawable; + stopAnimation(); + } + } + } + + /** + *

Get the drawable used to draw the progress bar in + * indeterminate mode.

+ * + * @return a {@link android.graphics.drawable.Drawable} instance + * + * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable) + * @see #setIndeterminate(boolean) + */ + public Drawable getIndeterminateDrawable() { + return mIndeterminateDrawable; + } + + /** + *

Define the drawable used to draw the progress bar in + * indeterminate mode.

+ * + * @param d the new drawable + * + * @see #getIndeterminateDrawable() + * @see #setIndeterminate(boolean) + */ + public void setIndeterminateDrawable(Drawable d) { + if (d != null) { + d.setCallback(this); + } + mIndeterminateDrawable = d; + if (mIndeterminate) { + mCurrentDrawable = d; + postInvalidate(); + } + } + + /** + *

Get the drawable used to draw the progress bar in + * progress mode.

+ * + * @return a {@link android.graphics.drawable.Drawable} instance + * + * @see #setProgressDrawable(android.graphics.drawable.Drawable) + * @see #setIndeterminate(boolean) + */ + public Drawable getProgressDrawable() { + return mProgressDrawable; + } + + /** + *

Define the drawable used to draw the progress bar in + * progress mode.

+ * + * @param d the new drawable + * + * @see #getProgressDrawable() + * @see #setIndeterminate(boolean) + */ + public void setProgressDrawable(Drawable d) { + boolean needUpdate; + if (mProgressDrawable != null && d != mProgressDrawable) { + mProgressDrawable.setCallback(null); + needUpdate = true; + } else { + needUpdate = false; + } + + if (d != null) { + d.setCallback(this); + + // Make sure the ProgressBar is always tall enough + int drawableHeight = d.getMinimumHeight(); + if (mMaxHeight < drawableHeight) { + mMaxHeight = drawableHeight; + requestLayout(); + } + } + mProgressDrawable = d; + if (!mIndeterminate) { + mCurrentDrawable = d; + postInvalidate(); + } + + if (needUpdate) { + updateDrawableBounds(getWidth(), getHeight()); + updateDrawableState(); + doRefreshProgress(android.R.id.progress, mProgress, false, false); + doRefreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false, false); + } + } + + /** + * @return The drawable currently used to draw the progress bar + */ + Drawable getCurrentDrawable() { + return mCurrentDrawable; + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mProgressDrawable || who == mIndeterminateDrawable + || super.verifyDrawable(who); + } + + @Override + public void jumpDrawablesToCurrentState() { + super.jumpDrawablesToCurrentState(); + if (mProgressDrawable != null) mProgressDrawable.jumpToCurrentState(); + if (mIndeterminateDrawable != null) mIndeterminateDrawable.jumpToCurrentState(); + } + + @Override + public void postInvalidate() { + if (!mNoInvalidate) { + super.postInvalidate(); + } + } + + private class RefreshProgressRunnable implements Runnable { + + private int mId; + private int mProgress; + private boolean mFromUser; + + RefreshProgressRunnable(int id, int progress, boolean fromUser) { + mId = id; + mProgress = progress; + mFromUser = fromUser; + } + + public void run() { + doRefreshProgress(mId, mProgress, mFromUser, true); + // Put ourselves back in the cache when we are done + mRefreshProgressRunnable = this; + } + + public void setup(int id, int progress, boolean fromUser) { + mId = id; + mProgress = progress; + mFromUser = fromUser; + } + + } + + private synchronized void doRefreshProgress(int id, int progress, boolean fromUser, + boolean callBackToApp) { + float scale = mMax > 0 ? (float) progress / (float) mMax : 0; + final Drawable d = mCurrentDrawable; + if (d != null) { + Drawable progressDrawable = null; + + if (d instanceof LayerDrawable) { + progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id); + } + + final int level = (int) (scale * MAX_LEVEL); + (progressDrawable != null ? progressDrawable : d).setLevel(level); + } else { + invalidate(); + } + + if (callBackToApp && id == android.R.id.progress) { + onProgressRefresh(scale, fromUser); + } + } + + void onProgressRefresh(float scale, boolean fromUser) { + if (mAccessibilityManager.isEnabled()) { + scheduleAccessibilityEventSender(); + } + } + + private synchronized void refreshProgress(int id, int progress, boolean fromUser) { + if (mUiThreadId == Thread.currentThread().getId()) { + doRefreshProgress(id, progress, fromUser, true); + } else { + RefreshProgressRunnable r; + if (mRefreshProgressRunnable != null) { + // Use cached RefreshProgressRunnable if available + r = mRefreshProgressRunnable; + // Uncache it + mRefreshProgressRunnable = null; + r.setup(id, progress, fromUser); + } else { + // Make a new one + r = new RefreshProgressRunnable(id, progress, fromUser); + } + post(r); + } + } + + /** + *

Set the current progress to the specified value. Does not do anything + * if the progress bar is in indeterminate mode.

+ * + * @param progress the new progress, between 0 and {@link #getMax()} + * + * @see #setIndeterminate(boolean) + * @see #isIndeterminate() + * @see #getProgress() + * @see #incrementProgressBy(int) + */ + public synchronized void setProgress(int progress) { + setProgress(progress, false); + } + + synchronized void setProgress(int progress, boolean fromUser) { + if (mIndeterminate) { + return; + } + + if (progress < 0) { + progress = 0; + } + + if (progress > mMax) { + progress = mMax; + } + + if (progress != mProgress) { + mProgress = progress; + refreshProgress(android.R.id.progress, mProgress, fromUser); + } + } + + /** + *

+ * Set the current secondary progress to the specified value. Does not do + * anything if the progress bar is in indeterminate mode. + *

+ * + * @param secondaryProgress the new secondary progress, between 0 and {@link #getMax()} + * @see #setIndeterminate(boolean) + * @see #isIndeterminate() + * @see #getSecondaryProgress() + * @see #incrementSecondaryProgressBy(int) + */ + public synchronized void setSecondaryProgress(int secondaryProgress) { + if (mIndeterminate) { + return; + } + + if (secondaryProgress < 0) { + secondaryProgress = 0; + } + + if (secondaryProgress > mMax) { + secondaryProgress = mMax; + } + + if (secondaryProgress != mSecondaryProgress) { + mSecondaryProgress = secondaryProgress; + refreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false); + } + } + + /** + *

Get the progress bar's current level of progress. Return 0 when the + * progress bar is in indeterminate mode.

+ * + * @return the current progress, between 0 and {@link #getMax()} + * + * @see #setIndeterminate(boolean) + * @see #isIndeterminate() + * @see #setProgress(int) + * @see #setMax(int) + * @see #getMax() + */ + @ViewDebug.ExportedProperty(category = "progress") + public synchronized int getProgress() { + return mIndeterminate ? 0 : mProgress; + } + + /** + *

Get the progress bar's current level of secondary progress. Return 0 when the + * progress bar is in indeterminate mode.

+ * + * @return the current secondary progress, between 0 and {@link #getMax()} + * + * @see #setIndeterminate(boolean) + * @see #isIndeterminate() + * @see #setSecondaryProgress(int) + * @see #setMax(int) + * @see #getMax() + */ + @ViewDebug.ExportedProperty(category = "progress") + public synchronized int getSecondaryProgress() { + return mIndeterminate ? 0 : mSecondaryProgress; + } + + /** + *

Return the upper limit of this progress bar's range.

+ * + * @return a positive integer + * + * @see #setMax(int) + * @see #getProgress() + * @see #getSecondaryProgress() + */ + @ViewDebug.ExportedProperty(category = "progress") + public synchronized int getMax() { + return mMax; + } + + /** + *

Set the range of the progress bar to 0...max.

+ * + * @param max the upper range of this progress bar + * + * @see #getMax() + * @see #setProgress(int) + * @see #setSecondaryProgress(int) + */ + public synchronized void setMax(int max) { + if (max < 0) { + max = 0; + } + if (max != mMax) { + mMax = max; + postInvalidate(); + + if (mProgress > max) { + mProgress = max; + } + refreshProgress(android.R.id.progress, mProgress, false); + } + } + + /** + *

Increase the progress bar's progress by the specified amount.

+ * + * @param diff the amount by which the progress must be increased + * + * @see #setProgress(int) + */ + public synchronized final void incrementProgressBy(int diff) { + setProgress(mProgress + diff); + } + + /** + *

Increase the progress bar's secondary progress by the specified amount.

+ * + * @param diff the amount by which the secondary progress must be increased + * + * @see #setSecondaryProgress(int) + */ + public synchronized final void incrementSecondaryProgressBy(int diff) { + setSecondaryProgress(mSecondaryProgress + diff); + } + + /** + *

Start the indeterminate progress animation.

+ */ + void startAnimation() { + if (getVisibility() != VISIBLE) { + return; + } + + if (mIndeterminateDrawable instanceof Animatable) { + mShouldStartAnimationDrawable = true; + mAnimation = null; + } else { + if (mInterpolator == null) { + mInterpolator = new LinearInterpolator(); + } + + mTransformation = new Transformation(); + mAnimation = new AlphaAnimation(0.0f, 1.0f); + mAnimation.setRepeatMode(mBehavior); + mAnimation.setRepeatCount(Animation.INFINITE); + mAnimation.setDuration(mDuration); + mAnimation.setInterpolator(mInterpolator); + mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME); + } + postInvalidate(); + } + + /** + *

Stop the indeterminate progress animation.

+ */ + void stopAnimation() { + mAnimation = null; + mTransformation = null; + if (mIndeterminateDrawable instanceof Animatable) { + ((Animatable) mIndeterminateDrawable).stop(); + mShouldStartAnimationDrawable = false; + } + postInvalidate(); + } + + /** + * Sets the acceleration curve for the indeterminate animation. + * The interpolator is loaded as a resource from the specified context. + * + * @param context The application environment + * @param resID The resource identifier of the interpolator to load + */ + public void setInterpolator(Context context, int resID) { + setInterpolator(AnimationUtils.loadInterpolator(context, resID)); + } + + /** + * Sets the acceleration curve for the indeterminate animation. + * Defaults to a linear interpolation. + * + * @param interpolator The interpolator which defines the acceleration curve + */ + public void setInterpolator(Interpolator interpolator) { + mInterpolator = interpolator; + } + + /** + * Gets the acceleration curve type for the indeterminate animation. + * + * @return the {@link Interpolator} associated to this animation + */ + public Interpolator getInterpolator() { + return mInterpolator; + } + + @Override + public void setVisibility(int v) { + if (getVisibility() != v) { + super.setVisibility(v); + + if (mIndeterminate) { + // let's be nice with the UI thread + if (v == GONE || v == INVISIBLE) { + stopAnimation(); + } else { + startAnimation(); + } + } + } + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + + if (mIndeterminate) { + // let's be nice with the UI thread + if (visibility == GONE || visibility == INVISIBLE) { + stopAnimation(); + } else { + startAnimation(); + } + } + } + + @Override + public void invalidateDrawable(Drawable dr) { + if (!mInDrawing) { + if (verifyDrawable(dr)) { + final Rect dirty = dr.getBounds(); + final int scrollX = getScrollX() + getPaddingLeft(); + final int scrollY = getScrollY() + getPaddingTop(); + + invalidate(dirty.left + scrollX, dirty.top + scrollY, + dirty.right + scrollX, dirty.bottom + scrollY); + } else { + super.invalidateDrawable(dr); + } + } + } + + /** + * @hide + * + @Override + public int getResolvedLayoutDirection(Drawable who) { + return (who == mProgressDrawable || who == mIndeterminateDrawable) ? + getResolvedLayoutDirection() : super.getResolvedLayoutDirection(who); + } + */ + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + updateDrawableBounds(w, h); + } + + private void updateDrawableBounds(int w, int h) { + // onDraw will translate the canvas so we draw starting at 0,0 + int right = w - getPaddingRight() - getPaddingLeft(); + int bottom = h - getPaddingBottom() - getPaddingTop(); + int top = 0; + int left = 0; + + if (mIndeterminateDrawable != null) { + // Aspect ratio logic does not apply to AnimationDrawables + if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) { + // Maintain aspect ratio. Certain kinds of animated drawables + // get very confused otherwise. + final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth(); + final int intrinsicHeight = mIndeterminateDrawable.getIntrinsicHeight(); + final float intrinsicAspect = (float) intrinsicWidth / intrinsicHeight; + final float boundAspect = (float) w / h; + if (intrinsicAspect != boundAspect) { + if (boundAspect > intrinsicAspect) { + // New width is larger. Make it smaller to match height. + final int width = (int) (h * intrinsicAspect); + left = (w - width) / 2; + right = left + width; + } else { + // New height is larger. Make it smaller to match width. + final int height = (int) (w * (1 / intrinsicAspect)); + top = (h - height) / 2; + bottom = top + height; + } + } + } + mIndeterminateDrawable.setBounds(0, 0, right - left, bottom - top); + mIndeterminateRealLeft = left; + mIndeterminateRealTop = top; + } + + if (mProgressDrawable != null) { + mProgressDrawable.setBounds(0, 0, right, bottom); + } + } + + @Override + protected synchronized void onDraw(Canvas canvas) { + super.onDraw(canvas); + + Drawable d = mCurrentDrawable; + if (d != null) { + // Translate canvas so a indeterminate circular progress bar with padding + // rotates properly in its animation + canvas.save(); + canvas.translate(getPaddingLeft() + mIndeterminateRealLeft, getPaddingTop() + mIndeterminateRealTop); + long time = getDrawingTime(); + if (mAnimation != null) { + mAnimation.getTransformation(time, mTransformation); + float scale = mTransformation.getAlpha(); + try { + mInDrawing = true; + d.setLevel((int) (scale * MAX_LEVEL)); + } finally { + mInDrawing = false; + } + if (SystemClock.uptimeMillis() - mLastDrawTime >= mAnimationResolution) { + mLastDrawTime = SystemClock.uptimeMillis(); + postInvalidateDelayed(mAnimationResolution); + } + } + d.draw(canvas); + canvas.restore(); + if (mShouldStartAnimationDrawable && d instanceof Animatable) { + ((Animatable) d).start(); + mShouldStartAnimationDrawable = false; + } + } + } + + @Override + protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + Drawable d = mCurrentDrawable; + + int dw = 0; + int dh = 0; + if (d != null) { + dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth())); + dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight())); + } + updateDrawableState(); + dw += getPaddingLeft() + getPaddingRight(); + dh += getPaddingTop() + getPaddingBottom(); + + if (IS_HONEYCOMB) { + setMeasuredDimension(View.resolveSizeAndState(dw, widthMeasureSpec, 0), + View.resolveSizeAndState(dh, heightMeasureSpec, 0)); + } else { + setMeasuredDimension(View.resolveSize(dw, widthMeasureSpec), + View.resolveSize(dh, heightMeasureSpec)); + } + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + updateDrawableState(); + } + + private void updateDrawableState() { + int[] state = getDrawableState(); + + if (mProgressDrawable != null && mProgressDrawable.isStateful()) { + mProgressDrawable.setState(state); + } + + if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) { + mIndeterminateDrawable.setState(state); + } + } + + static class SavedState extends BaseSavedState { + int progress; + int secondaryProgress; + + /** + * Constructor called from {@link IcsProgressBar#onSaveInstanceState()} + */ + SavedState(Parcelable superState) { + super(superState); + } + + /** + * Constructor called from {@link #CREATOR} + */ + private SavedState(Parcel in) { + super(in); + progress = in.readInt(); + secondaryProgress = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(progress); + out.writeInt(secondaryProgress); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + } + + @Override + public Parcelable onSaveInstanceState() { + // Force our ancestor class to save its state + Parcelable superState = super.onSaveInstanceState(); + SavedState ss = new SavedState(superState); + + ss.progress = mProgress; + ss.secondaryProgress = mSecondaryProgress; + + return ss; + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + SavedState ss = (SavedState) state; + super.onRestoreInstanceState(ss.getSuperState()); + + setProgress(ss.progress); + setSecondaryProgress(ss.secondaryProgress); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mIndeterminate) { + startAnimation(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mIndeterminate) { + stopAnimation(); + } + if(mRefreshProgressRunnable != null) { + removeCallbacks(mRefreshProgressRunnable); + } + if (mAccessibilityEventSender != null) { + removeCallbacks(mAccessibilityEventSender); + } + // This should come after stopAnimation(), otherwise an invalidate message remains in the + // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation + super.onDetachedFromWindow(); + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setItemCount(mMax); + event.setCurrentItemIndex(mProgress); + } + + /** + * Schedule a command for sending an accessibility event. + *
+ * Note: A command is used to ensure that accessibility events + * are sent at most one in a given time frame to save + * system resources while the progress changes quickly. + */ + private void scheduleAccessibilityEventSender() { + if (mAccessibilityEventSender == null) { + mAccessibilityEventSender = new AccessibilityEventSender(); + } else { + removeCallbacks(mAccessibilityEventSender); + } + postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT); + } + + /** + * Command for sending an accessibility event. + */ + private class AccessibilityEventSender implements Runnable { + public void run() { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java new file mode 100644 index 000000000..038d1e031 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsSpinner.java @@ -0,0 +1,703 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.internal.widget; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; +import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; +import com.actionbarsherlock.R; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.PopupWindow; +import android.widget.SpinnerAdapter; + + +/** + * A view that displays one child at a time and lets the user pick among them. + * The items in the Spinner come from the {@link Adapter} associated with + * this view. + * + *

See the Spinner + * tutorial.

+ * + * @attr ref android.R.styleable#Spinner_prompt + */ +public class IcsSpinner extends IcsAbsSpinner implements OnClickListener { + //private static final String TAG = "Spinner"; + + // Only measure this many items to get a decent max width. + private static final int MAX_ITEMS_MEASURED = 15; + + /** + * Use a dialog window for selecting spinner options. + */ + //public static final int MODE_DIALOG = 0; + + /** + * Use a dropdown anchored to the Spinner for selecting spinner options. + */ + public static final int MODE_DROPDOWN = 1; + + /** + * Use the theme-supplied value to select the dropdown mode. + */ + //private static final int MODE_THEME = -1; + + private SpinnerPopup mPopup; + private DropDownAdapter mTempAdapter; + int mDropDownWidth; + + private int mGravity; + private boolean mDisableChildrenWhenDisabled; + + private Rect mTempRect = new Rect(); + + public IcsSpinner(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.actionDropDownStyle); + } + + /** + * Construct a new spinner with the given context's theme, the supplied attribute set, + * and default style. + * + * @param context The Context the view is running in, through which it can + * access the current theme, resources, etc. + * @param attrs The attributes of the XML tag that is inflating the view. + * @param defStyle The default style to apply to this view. If 0, no style + * will be applied (beyond what is included in the theme). This may + * either be an attribute resource, whose value will be retrieved + * from the current theme, or an explicit style resource. + */ + public IcsSpinner(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, + R.styleable.SherlockSpinner, defStyle, 0); + + + DropdownPopup popup = new DropdownPopup(context, attrs, defStyle); + + mDropDownWidth = a.getLayoutDimension( + R.styleable.SherlockSpinner_android_dropDownWidth, + ViewGroup.LayoutParams.WRAP_CONTENT); + popup.setBackgroundDrawable(a.getDrawable( + R.styleable.SherlockSpinner_android_popupBackground)); + final int verticalOffset = a.getDimensionPixelOffset( + R.styleable.SherlockSpinner_android_dropDownVerticalOffset, 0); + if (verticalOffset != 0) { + popup.setVerticalOffset(verticalOffset); + } + + final int horizontalOffset = a.getDimensionPixelOffset( + R.styleable.SherlockSpinner_android_dropDownHorizontalOffset, 0); + if (horizontalOffset != 0) { + popup.setHorizontalOffset(horizontalOffset); + } + + mPopup = popup; + + mGravity = a.getInt(R.styleable.SherlockSpinner_android_gravity, Gravity.CENTER); + + mPopup.setPromptText(a.getString(R.styleable.SherlockSpinner_android_prompt)); + + mDisableChildrenWhenDisabled = true; + + a.recycle(); + + // Base constructor can call setAdapter before we initialize mPopup. + // Finish setting things up if this happened. + if (mTempAdapter != null) { + mPopup.setAdapter(mTempAdapter); + mTempAdapter = null; + } + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (mDisableChildrenWhenDisabled) { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + getChildAt(i).setEnabled(enabled); + } + } + } + + /** + * Describes how the selected item view is positioned. Currently only the horizontal component + * is used. The default is determined by the current theme. + * + * @param gravity See {@link android.view.Gravity} + * + * @attr ref android.R.styleable#Spinner_gravity + */ + public void setGravity(int gravity) { + if (mGravity != gravity) { + if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) { + gravity |= Gravity.LEFT; + } + mGravity = gravity; + requestLayout(); + } + } + + @Override + public void setAdapter(SpinnerAdapter adapter) { + super.setAdapter(adapter); + + if (mPopup != null) { + mPopup.setAdapter(new DropDownAdapter(adapter)); + } else { + mTempAdapter = new DropDownAdapter(adapter); + } + } + + @Override + public int getBaseline() { + View child = null; + + if (getChildCount() > 0) { + child = getChildAt(0); + } else if (mAdapter != null && mAdapter.getCount() > 0) { + child = makeAndAddView(0); + mRecycler.put(0, child); + removeAllViewsInLayout(); + } + + if (child != null) { + final int childBaseline = child.getBaseline(); + return childBaseline >= 0 ? child.getTop() + childBaseline : -1; + } else { + return -1; + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + if (mPopup != null && mPopup.isShowing()) { + mPopup.dismiss(); + } + } + + /** + *

A spinner does not support item click events. Calling this method + * will raise an exception.

+ * + * @param l this listener will be ignored + */ + @Override + public void setOnItemClickListener(OnItemClickListener l) { + throw new RuntimeException("setOnItemClickListener cannot be used with a spinner."); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { + final int measuredWidth = getMeasuredWidth(); + setMeasuredDimension(Math.min(Math.max(measuredWidth, + measureContentWidth(getAdapter(), getBackground())), + MeasureSpec.getSize(widthMeasureSpec)), + getMeasuredHeight()); + } + } + + /** + * @see android.view.View#onLayout(boolean,int,int,int,int) + * + * Creates and positions all views + * + */ + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + mInLayout = true; + layout(0, false); + mInLayout = false; + } + + /** + * Creates and positions all views for this Spinner. + * + * @param delta Change in the selected position. +1 moves selection is moving to the right, + * so views are scrolling to the left. -1 means selection is moving to the left. + */ + @Override + void layout(int delta, boolean animate) { + int childrenLeft = mSpinnerPadding.left; + int childrenWidth = getRight() - getLeft() - mSpinnerPadding.left - mSpinnerPadding.right; + + if (mDataChanged) { + handleDataChanged(); + } + + // Handle the empty set by removing all views + if (mItemCount == 0) { + resetList(); + return; + } + + if (mNextSelectedPosition >= 0) { + setSelectedPositionInt(mNextSelectedPosition); + } + + recycleAllViews(); + + // Clear out old views + removeAllViewsInLayout(); + + // Make selected view and position it + mFirstPosition = mSelectedPosition; + View sel = makeAndAddView(mSelectedPosition); + int width = sel.getMeasuredWidth(); + int selectedOffset = childrenLeft; + switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2); + break; + case Gravity.RIGHT: + selectedOffset = childrenLeft + childrenWidth - width; + break; + } + sel.offsetLeftAndRight(selectedOffset); + + // Flush any cached views that did not get reused above + mRecycler.clear(); + + invalidate(); + + checkSelectionChanged(); + + mDataChanged = false; + mNeedSync = false; + setNextSelectedPositionInt(mSelectedPosition); + } + + /** + * Obtain a view, either by pulling an existing view from the recycler or + * by getting a new one from the adapter. If we are animating, make sure + * there is enough information in the view's layout parameters to animate + * from the old to new positions. + * + * @param position Position in the spinner for the view to obtain + * @return A view that has been added to the spinner + */ + private View makeAndAddView(int position) { + + View child; + + if (!mDataChanged) { + child = mRecycler.get(position); + if (child != null) { + // Position the view + setUpChild(child); + + return child; + } + } + + // Nothing found in the recycler -- ask the adapter for a view + child = mAdapter.getView(position, null, this); + + // Position the view + setUpChild(child); + + return child; + } + + /** + * Helper for makeAndAddView to set the position of a view + * and fill out its layout paramters. + * + * @param child The view to position + */ + private void setUpChild(View child) { + + // Respect layout params that are already in the view. Otherwise + // make some up... + ViewGroup.LayoutParams lp = child.getLayoutParams(); + if (lp == null) { + lp = generateDefaultLayoutParams(); + } + + addViewInLayout(child, 0, lp); + + child.setSelected(hasFocus()); + if (mDisableChildrenWhenDisabled) { + child.setEnabled(isEnabled()); + } + + // Get measure specs + int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, + mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height); + int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, + mSpinnerPadding.left + mSpinnerPadding.right, lp.width); + + // Measure child + child.measure(childWidthSpec, childHeightSpec); + + int childLeft; + int childRight; + + // Position vertically based on gravity setting + int childTop = mSpinnerPadding.top + + ((getMeasuredHeight() - mSpinnerPadding.bottom - + mSpinnerPadding.top - child.getMeasuredHeight()) / 2); + int childBottom = childTop + child.getMeasuredHeight(); + + int width = child.getMeasuredWidth(); + childLeft = 0; + childRight = childLeft + width; + + child.layout(childLeft, childTop, childRight, childBottom); + } + + @Override + public boolean performClick() { + boolean handled = super.performClick(); + + if (!handled) { + handled = true; + + if (!mPopup.isShowing()) { + mPopup.show(); + } + } + + return handled; + } + + public void onClick(DialogInterface dialog, int which) { + setSelection(which); + dialog.dismiss(); + } + + /** + * Sets the prompt to display when the dialog is shown. + * @param prompt the prompt to set + */ + public void setPrompt(CharSequence prompt) { + mPopup.setPromptText(prompt); + } + + /** + * Sets the prompt to display when the dialog is shown. + * @param promptId the resource ID of the prompt to display when the dialog is shown + */ + public void setPromptId(int promptId) { + setPrompt(getContext().getText(promptId)); + } + + /** + * @return The prompt to display when the dialog is shown + */ + public CharSequence getPrompt() { + return mPopup.getHintText(); + } + + int measureContentWidth(SpinnerAdapter adapter, Drawable background) { + if (adapter == null) { + return 0; + } + + int width = 0; + View itemView = null; + int itemType = 0; + final int widthMeasureSpec = + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final int heightMeasureSpec = + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + + // Make sure the number of items we'll measure is capped. If it's a huge data set + // with wildly varying sizes, oh well. + int start = Math.max(0, getSelectedItemPosition()); + final int end = Math.min(adapter.getCount(), start + MAX_ITEMS_MEASURED); + final int count = end - start; + start = Math.max(0, start - (MAX_ITEMS_MEASURED - count)); + for (int i = start; i < end; i++) { + final int positionType = adapter.getItemViewType(i); + if (positionType != itemType) { + itemType = positionType; + itemView = null; + } + itemView = adapter.getView(i, itemView, this); + if (itemView.getLayoutParams() == null) { + itemView.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT)); + } + itemView.measure(widthMeasureSpec, heightMeasureSpec); + width = Math.max(width, itemView.getMeasuredWidth()); + } + + // Add background padding to measured width + if (background != null) { + background.getPadding(mTempRect); + width += mTempRect.left + mTempRect.right; + } + + return width; + } + + /** + *

Wrapper class for an Adapter. Transforms the embedded Adapter instance + * into a ListAdapter.

+ */ + private static class DropDownAdapter implements ListAdapter, SpinnerAdapter { + private SpinnerAdapter mAdapter; + private ListAdapter mListAdapter; + + /** + *

Creates a new ListAdapter wrapper for the specified adapter.

+ * + * @param adapter the Adapter to transform into a ListAdapter + */ + public DropDownAdapter(SpinnerAdapter adapter) { + this.mAdapter = adapter; + if (adapter instanceof ListAdapter) { + this.mListAdapter = (ListAdapter) adapter; + } + } + + public int getCount() { + return mAdapter == null ? 0 : mAdapter.getCount(); + } + + public Object getItem(int position) { + return mAdapter == null ? null : mAdapter.getItem(position); + } + + public long getItemId(int position) { + return mAdapter == null ? -1 : mAdapter.getItemId(position); + } + + public View getView(int position, View convertView, ViewGroup parent) { + return getDropDownView(position, convertView, parent); + } + + public View getDropDownView(int position, View convertView, ViewGroup parent) { + return mAdapter == null ? null : + mAdapter.getDropDownView(position, convertView, parent); + } + + public boolean hasStableIds() { + return mAdapter != null && mAdapter.hasStableIds(); + } + + public void registerDataSetObserver(DataSetObserver observer) { + if (mAdapter != null) { + mAdapter.registerDataSetObserver(observer); + } + } + + public void unregisterDataSetObserver(DataSetObserver observer) { + if (mAdapter != null) { + mAdapter.unregisterDataSetObserver(observer); + } + } + + /** + * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call. + * Otherwise, return true. + */ + public boolean areAllItemsEnabled() { + final ListAdapter adapter = mListAdapter; + if (adapter != null) { + return adapter.areAllItemsEnabled(); + } else { + return true; + } + } + + /** + * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call. + * Otherwise, return true. + */ + public boolean isEnabled(int position) { + final ListAdapter adapter = mListAdapter; + if (adapter != null) { + return adapter.isEnabled(position); + } else { + return true; + } + } + + public int getItemViewType(int position) { + return 0; + } + + public int getViewTypeCount() { + return 1; + } + + public boolean isEmpty() { + return getCount() == 0; + } + } + + /** + * Implements some sort of popup selection interface for selecting a spinner option. + * Allows for different spinner modes. + */ + private interface SpinnerPopup { + public void setAdapter(ListAdapter adapter); + + /** + * Show the popup + */ + public void show(); + + /** + * Dismiss the popup + */ + public void dismiss(); + + /** + * @return true if the popup is showing, false otherwise. + */ + public boolean isShowing(); + + /** + * Set hint text to be displayed to the user. This should provide + * a description of the choice being made. + * @param hintText Hint text to set. + */ + public void setPromptText(CharSequence hintText); + public CharSequence getHintText(); + } + + /* + private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener { + private AlertDialog mPopup; + private ListAdapter mListAdapter; + private CharSequence mPrompt; + + public void dismiss() { + mPopup.dismiss(); + mPopup = null; + } + + public boolean isShowing() { + return mPopup != null ? mPopup.isShowing() : false; + } + + public void setAdapter(ListAdapter adapter) { + mListAdapter = adapter; + } + + public void setPromptText(CharSequence hintText) { + mPrompt = hintText; + } + + public CharSequence getHintText() { + return mPrompt; + } + + public void show() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + if (mPrompt != null) { + builder.setTitle(mPrompt); + } + mPopup = builder.setSingleChoiceItems(mListAdapter, + getSelectedItemPosition(), this).show(); + } + + public void onClick(DialogInterface dialog, int which) { + setSelection(which); + dismiss(); + } + } + */ + + private class DropdownPopup extends IcsListPopupWindow implements SpinnerPopup { + private CharSequence mHintText; + private ListAdapter mAdapter; + + public DropdownPopup(Context context, AttributeSet attrs, int defStyleRes) { + super(context, attrs, 0, defStyleRes); + + setAnchorView(IcsSpinner.this); + setModal(true); + setPromptPosition(POSITION_PROMPT_ABOVE); + setOnItemClickListener(new OnItemClickListener() { + @SuppressWarnings("rawtypes") + public void onItemClick(AdapterView parent, View v, int position, long id) { + IcsSpinner.this.setSelection(position); + dismiss(); + } + }); + } + + @Override + public void setAdapter(ListAdapter adapter) { + super.setAdapter(adapter); + mAdapter = adapter; + } + + public CharSequence getHintText() { + return mHintText; + } + + public void setPromptText(CharSequence hintText) { + // Hint text is ignored for dropdowns, but maintain it here. + mHintText = hintText; + } + + @Override + public void show() { + final int spinnerPaddingLeft = IcsSpinner.this.getPaddingLeft(); + if (mDropDownWidth == WRAP_CONTENT) { + final int spinnerWidth = IcsSpinner.this.getWidth(); + final int spinnerPaddingRight = IcsSpinner.this.getPaddingRight(); + setContentWidth(Math.max( + measureContentWidth((SpinnerAdapter) mAdapter, getBackground()), + spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight)); + } else if (mDropDownWidth == MATCH_PARENT) { + final int spinnerWidth = IcsSpinner.this.getWidth(); + final int spinnerPaddingRight = IcsSpinner.this.getPaddingRight(); + setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight); + } else { + setContentWidth(mDropDownWidth); + } + final Drawable background = getBackground(); + int bgOffset = 0; + if (background != null) { + background.getPadding(mTempRect); + bgOffset = -mTempRect.left; + } + setHorizontalOffset(bgOffset + spinnerPaddingLeft); + setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); + super.show(); + getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); + setSelection(IcsSpinner.this.getSelectedItemPosition()); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java new file mode 100644 index 000000000..a7185d082 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/IcsView.java @@ -0,0 +1,21 @@ +package com.actionbarsherlock.internal.widget; + +import android.view.View; + +final class IcsView { + //No instances + private IcsView() {} + + /** + * Return only the state bits of {@link #getMeasuredWidthAndState()} + * and {@link #getMeasuredHeightAndState()}, combined into one integer. + * The width component is in the regular bits {@link #MEASURED_STATE_MASK} + * and the height component is at the shifted bits + * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}. + */ + public static int getMeasuredStateInt(View child) { + return (child.getMeasuredWidth()&View.MEASURED_STATE_MASK) + | ((child.getMeasuredHeight()>>View.MEASURED_HEIGHT_STATE_SHIFT) + & (View.MEASURED_STATE_MASK>>View.MEASURED_HEIGHT_STATE_SHIFT)); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java new file mode 100644 index 000000000..48fb5d8b4 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/internal/widget/ScrollingTabContainerView.java @@ -0,0 +1,546 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.actionbarsherlock.internal.widget; + +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.text.TextUtils.TruncateAt; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.widget.BaseAdapter; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import com.actionbarsherlock.R; +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.internal.nineoldandroids.animation.Animator; +import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator; +import com.actionbarsherlock.internal.nineoldandroids.widget.NineHorizontalScrollView; + +/** + * This widget implements the dynamic action bar tab behavior that can change + * across different configurations or circumstances. + */ +public class ScrollingTabContainerView extends NineHorizontalScrollView + implements IcsAdapterView.OnItemSelectedListener { + //UNUSED private static final String TAG = "ScrollingTabContainerView"; + Runnable mTabSelector; + private TabClickListener mTabClickListener; + + private IcsLinearLayout mTabLayout; + private IcsSpinner mTabSpinner; + private boolean mAllowCollapse; + + private LayoutInflater mInflater; + + int mMaxTabWidth; + private int mContentHeight; + private int mSelectedTabIndex; + + protected Animator mVisibilityAnim; + protected final VisibilityAnimListener mVisAnimListener = new VisibilityAnimListener(); + + private static final /*Time*/Interpolator sAlphaInterpolator = new DecelerateInterpolator(); + + private static final int FADE_DURATION = 200; + + public ScrollingTabContainerView(Context context) { + super(context); + setHorizontalScrollBarEnabled(false); + + TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, + R.attr.actionBarStyle, 0); + setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); + a.recycle(); + + mInflater = LayoutInflater.from(context); + + mTabLayout = createTabLayout(); + addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + final boolean lockedExpanded = widthMode == MeasureSpec.EXACTLY; + setFillViewport(lockedExpanded); + + final int childCount = mTabLayout.getChildCount(); + if (childCount > 1 && + (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST)) { + if (childCount > 2) { + mMaxTabWidth = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.4f); + } else { + mMaxTabWidth = MeasureSpec.getSize(widthMeasureSpec) / 2; + } + } else { + mMaxTabWidth = -1; + } + + heightMeasureSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY); + + final boolean canCollapse = !lockedExpanded && mAllowCollapse; + + if (canCollapse) { + // See if we should expand + mTabLayout.measure(MeasureSpec.UNSPECIFIED, heightMeasureSpec); + if (mTabLayout.getMeasuredWidth() > MeasureSpec.getSize(widthMeasureSpec)) { + performCollapse(); + } else { + performExpand(); + } + } else { + performExpand(); + } + + final int oldWidth = getMeasuredWidth(); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + final int newWidth = getMeasuredWidth(); + + if (lockedExpanded && oldWidth != newWidth) { + // Recenter the tab display if we're at a new (scrollable) size. + setTabSelected(mSelectedTabIndex); + } + } + + /** + * Indicates whether this view is collapsed into a dropdown menu instead + * of traditional tabs. + * @return true if showing as a spinner + */ + private boolean isCollapsed() { + return mTabSpinner != null && mTabSpinner.getParent() == this; + } + + public void setAllowCollapse(boolean allowCollapse) { + mAllowCollapse = allowCollapse; + } + + private void performCollapse() { + if (isCollapsed()) return; + + if (mTabSpinner == null) { + mTabSpinner = createSpinner(); + } + removeView(mTabLayout); + addView(mTabSpinner, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + if (mTabSpinner.getAdapter() == null) { + mTabSpinner.setAdapter(new TabAdapter()); + } + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + mTabSelector = null; + } + mTabSpinner.setSelection(mSelectedTabIndex); + } + + private boolean performExpand() { + if (!isCollapsed()) return false; + + removeView(mTabSpinner); + addView(mTabLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + setTabSelected(mTabSpinner.getSelectedItemPosition()); + return false; + } + + public void setTabSelected(int position) { + mSelectedTabIndex = position; + final int tabCount = mTabLayout.getChildCount(); + for (int i = 0; i < tabCount; i++) { + final View child = mTabLayout.getChildAt(i); + final boolean isSelected = i == position; + child.setSelected(isSelected); + if (isSelected) { + animateToTab(position); + } + } + } + + public void setContentHeight(int contentHeight) { + mContentHeight = contentHeight; + requestLayout(); + } + + private IcsLinearLayout createTabLayout() { + final IcsLinearLayout tabLayout = (IcsLinearLayout) LayoutInflater.from(getContext()) + .inflate(R.layout.abs__action_bar_tab_bar_view, null); + tabLayout.setMeasureWithLargestChildEnabled(true); + tabLayout.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); + return tabLayout; + } + + private IcsSpinner createSpinner() { + final IcsSpinner spinner = new IcsSpinner(getContext(), null, + R.attr.actionDropDownStyle); + spinner.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); + spinner.setOnItemSelectedListener(this); + return spinner; + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + // Action bar can change size on configuration changes. + // Reread the desired height from the theme-specified style. + TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.SherlockActionBar, + R.attr.actionBarStyle, 0); + setContentHeight(a.getLayoutDimension(R.styleable.SherlockActionBar_height, 0)); + a.recycle(); + } + + public void animateToVisibility(int visibility) { + if (mVisibilityAnim != null) { + mVisibilityAnim.cancel(); + } + if (visibility == VISIBLE) { + if (getVisibility() != VISIBLE) { + setAlpha(0); + } + ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1); + anim.setDuration(FADE_DURATION); + anim.setInterpolator(sAlphaInterpolator); + + anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); + anim.start(); + } else { + ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0); + anim.setDuration(FADE_DURATION); + anim.setInterpolator(sAlphaInterpolator); + + anim.addListener(mVisAnimListener.withFinalVisibility(visibility)); + anim.start(); + } + } + + public void animateToTab(final int position) { + final View tabView = mTabLayout.getChildAt(position); + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + } + mTabSelector = new Runnable() { + public void run() { + final int scrollPos = tabView.getLeft() - (getWidth() - tabView.getWidth()) / 2; + smoothScrollTo(scrollPos, 0); + mTabSelector = null; + } + }; + post(mTabSelector); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + if (mTabSelector != null) { + // Re-post the selector we saved + post(mTabSelector); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mTabSelector != null) { + removeCallbacks(mTabSelector); + } + } + + private TabView createTabView(ActionBar.Tab tab, boolean forAdapter) { + //Workaround for not being able to pass a defStyle on pre-3.0 + final TabView tabView = (TabView)mInflater.inflate(R.layout.abs__action_bar_tab, null); + tabView.init(this, tab, forAdapter); + + if (forAdapter) { + tabView.setBackgroundDrawable(null); + tabView.setLayoutParams(new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, + mContentHeight)); + } else { + tabView.setFocusable(true); + + if (mTabClickListener == null) { + mTabClickListener = new TabClickListener(); + } + tabView.setOnClickListener(mTabClickListener); + } + return tabView; + } + + public void addTab(ActionBar.Tab tab, boolean setSelected) { + TabView tabView = createTabView(tab, false); + mTabLayout.addView(tabView, new IcsLinearLayout.LayoutParams(0, + LayoutParams.MATCH_PARENT, 1)); + if (mTabSpinner != null) { + ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); + } + if (setSelected) { + tabView.setSelected(true); + } + if (mAllowCollapse) { + requestLayout(); + } + } + + public void addTab(ActionBar.Tab tab, int position, boolean setSelected) { + final TabView tabView = createTabView(tab, false); + mTabLayout.addView(tabView, position, new IcsLinearLayout.LayoutParams( + 0, LayoutParams.MATCH_PARENT, 1)); + if (mTabSpinner != null) { + ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); + } + if (setSelected) { + tabView.setSelected(true); + } + if (mAllowCollapse) { + requestLayout(); + } + } + + public void updateTab(int position) { + ((TabView) mTabLayout.getChildAt(position)).update(); + if (mTabSpinner != null) { + ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); + } + if (mAllowCollapse) { + requestLayout(); + } + } + + public void removeTabAt(int position) { + mTabLayout.removeViewAt(position); + if (mTabSpinner != null) { + ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); + } + if (mAllowCollapse) { + requestLayout(); + } + } + + public void removeAllTabs() { + mTabLayout.removeAllViews(); + if (mTabSpinner != null) { + ((TabAdapter) mTabSpinner.getAdapter()).notifyDataSetChanged(); + } + if (mAllowCollapse) { + requestLayout(); + } + } + + @Override + public void onItemSelected(IcsAdapterView parent, View view, int position, long id) { + TabView tabView = (TabView) view; + tabView.getTab().select(); + } + + @Override + public void onNothingSelected(IcsAdapterView parent) { + } + + public static class TabView extends LinearLayout { + private ScrollingTabContainerView mParent; + private ActionBar.Tab mTab; + private CapitalizingTextView mTextView; + private ImageView mIconView; + private View mCustomView; + + public TabView(Context context, AttributeSet attrs) { + //TODO super(context, null, R.attr.actionBarTabStyle); + super(context, attrs); + } + + public void init(ScrollingTabContainerView parent, ActionBar.Tab tab, boolean forList) { + mParent = parent; + mTab = tab; + + if (forList) { + setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + } + + update(); + } + + public void bindTab(ActionBar.Tab tab) { + mTab = tab; + update(); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + // Re-measure if we went beyond our maximum size. + if (mParent.mMaxTabWidth > 0 && getMeasuredWidth() > mParent.mMaxTabWidth) { + super.onMeasure(MeasureSpec.makeMeasureSpec(mParent.mMaxTabWidth, MeasureSpec.EXACTLY), + heightMeasureSpec); + } + } + + public void update() { + final ActionBar.Tab tab = mTab; + final View custom = tab.getCustomView(); + if (custom != null) { + final ViewParent customParent = custom.getParent(); + if (customParent != this) { + if (customParent != null) ((ViewGroup) customParent).removeView(custom); + addView(custom); + } + mCustomView = custom; + if (mTextView != null) mTextView.setVisibility(GONE); + if (mIconView != null) { + mIconView.setVisibility(GONE); + mIconView.setImageDrawable(null); + } + } else { + if (mCustomView != null) { + removeView(mCustomView); + mCustomView = null; + } + + final Drawable icon = tab.getIcon(); + final CharSequence text = tab.getText(); + + if (icon != null) { + if (mIconView == null) { + ImageView iconView = new ImageView(getContext()); + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER_VERTICAL; + iconView.setLayoutParams(lp); + addView(iconView, 0); + mIconView = iconView; + } + mIconView.setImageDrawable(icon); + mIconView.setVisibility(VISIBLE); + } else if (mIconView != null) { + mIconView.setVisibility(GONE); + mIconView.setImageDrawable(null); + } + + if (text != null) { + if (mTextView == null) { + CapitalizingTextView textView = new CapitalizingTextView(getContext(), null, + R.attr.actionBarTabTextStyle); + textView.setEllipsize(TruncateAt.END); + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT); + lp.gravity = Gravity.CENTER_VERTICAL; + textView.setLayoutParams(lp); + addView(textView); + mTextView = textView; + } + mTextView.setTextCompat(text); + mTextView.setVisibility(VISIBLE); + } else if (mTextView != null) { + mTextView.setVisibility(GONE); + mTextView.setText(null); + } + + if (mIconView != null) { + mIconView.setContentDescription(tab.getContentDescription()); + } + } + } + + public ActionBar.Tab getTab() { + return mTab; + } + } + + private class TabAdapter extends BaseAdapter { + @Override + public int getCount() { + return mTabLayout.getChildCount(); + } + + @Override + public Object getItem(int position) { + return ((TabView) mTabLayout.getChildAt(position)).getTab(); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = createTabView((ActionBar.Tab) getItem(position), true); + } else { + ((TabView) convertView).bindTab((ActionBar.Tab) getItem(position)); + } + return convertView; + } + } + + private class TabClickListener implements OnClickListener { + public void onClick(View view) { + TabView tabView = (TabView) view; + tabView.getTab().select(); + final int tabCount = mTabLayout.getChildCount(); + for (int i = 0; i < tabCount; i++) { + final View child = mTabLayout.getChildAt(i); + child.setSelected(child == view); + } + } + } + + protected class VisibilityAnimListener implements Animator.AnimatorListener { + private boolean mCanceled = false; + private int mFinalVisibility; + + public VisibilityAnimListener withFinalVisibility(int visibility) { + mFinalVisibility = visibility; + return this; + } + + @Override + public void onAnimationStart(Animator animation) { + setVisibility(VISIBLE); + mVisibilityAnim = animation; + mCanceled = false; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (mCanceled) return; + + mVisibilityAnim = null; + setVisibility(mFinalVisibility); + } + + @Override + public void onAnimationCancel(Animator animation) { + mCanceled = true; + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java new file mode 100644 index 000000000..81b4cd4d2 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionMode.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import android.view.View; + + +/** + * Represents a contextual mode of the user interface. Action modes can be used for + * modal interactions with content and replace parts of the normal UI until finished. + * Examples of good action modes include selection modes, search, content editing, etc. + */ +public abstract class ActionMode { + private Object mTag; + + /** + * Set a tag object associated with this ActionMode. + * + *

Like the tag available to views, this allows applications to associate arbitrary + * data with an ActionMode for later reference. + * + * @param tag Tag to associate with this ActionMode + * + * @see #getTag() + */ + public void setTag(Object tag) { + mTag = tag; + } + + /** + * Retrieve the tag object associated with this ActionMode. + * + *

Like the tag available to views, this allows applications to associate arbitrary + * data with an ActionMode for later reference. + * + * @return Tag associated with this ActionMode + * + * @see #setTag(Object) + */ + public Object getTag() { + return mTag; + } + + /** + * Set the title of the action mode. This method will have no visible effect if + * a custom view has been set. + * + * @param title Title string to set + * + * @see #setTitle(int) + * @see #setCustomView(View) + */ + public abstract void setTitle(CharSequence title); + + /** + * Set the title of the action mode. This method will have no visible effect if + * a custom view has been set. + * + * @param resId Resource ID of a string to set as the title + * + * @see #setTitle(CharSequence) + * @see #setCustomView(View) + */ + public abstract void setTitle(int resId); + + /** + * Set the subtitle of the action mode. This method will have no visible effect if + * a custom view has been set. + * + * @param subtitle Subtitle string to set + * + * @see #setSubtitle(int) + * @see #setCustomView(View) + */ + public abstract void setSubtitle(CharSequence subtitle); + + /** + * Set the subtitle of the action mode. This method will have no visible effect if + * a custom view has been set. + * + * @param resId Resource ID of a string to set as the subtitle + * + * @see #setSubtitle(CharSequence) + * @see #setCustomView(View) + */ + public abstract void setSubtitle(int resId); + + /** + * Set a custom view for this action mode. The custom view will take the place of + * the title and subtitle. Useful for things like search boxes. + * + * @param view Custom view to use in place of the title/subtitle. + * + * @see #setTitle(CharSequence) + * @see #setSubtitle(CharSequence) + */ + public abstract void setCustomView(View view); + + /** + * Invalidate the action mode and refresh menu content. The mode's + * {@link ActionMode.Callback} will have its + * {@link Callback#onPrepareActionMode(ActionMode, Menu)} method called. + * If it returns true the menu will be scanned for updated content and any relevant changes + * will be reflected to the user. + */ + public abstract void invalidate(); + + /** + * Finish and close this action mode. The action mode's {@link ActionMode.Callback} will + * have its {@link Callback#onDestroyActionMode(ActionMode)} method called. + */ + public abstract void finish(); + + /** + * Returns the menu of actions that this action mode presents. + * @return The action mode's menu. + */ + public abstract Menu getMenu(); + + /** + * Returns the current title of this action mode. + * @return Title text + */ + public abstract CharSequence getTitle(); + + /** + * Returns the current subtitle of this action mode. + * @return Subtitle text + */ + public abstract CharSequence getSubtitle(); + + /** + * Returns the current custom view for this action mode. + * @return The current custom view + */ + public abstract View getCustomView(); + + /** + * Returns a {@link MenuInflater} with the ActionMode's context. + */ + public abstract MenuInflater getMenuInflater(); + + /** + * Returns whether the UI presenting this action mode can take focus or not. + * This is used by internal components within the framework that would otherwise + * present an action mode UI that requires focus, such as an EditText as a custom view. + * + * @return true if the UI used to show this action mode can take focus + * @hide Internal use only + */ + public boolean isUiFocusable() { + return true; + } + + /** + * Callback interface for action modes. Supplied to + * {@link View#startActionMode(Callback)}, a Callback + * configures and handles events raised by a user's interaction with an action mode. + * + *

An action mode's lifecycle is as follows: + *

    + *
  • {@link Callback#onCreateActionMode(ActionMode, Menu)} once on initial + * creation
  • + *
  • {@link Callback#onPrepareActionMode(ActionMode, Menu)} after creation + * and any time the {@link ActionMode} is invalidated
  • + *
  • {@link Callback#onActionItemClicked(ActionMode, MenuItem)} any time a + * contextual action button is clicked
  • + *
  • {@link Callback#onDestroyActionMode(ActionMode)} when the action mode + * is closed
  • + *
+ */ + public interface Callback { + /** + * Called when action mode is first created. The menu supplied will be used to + * generate action buttons for the action mode. + * + * @param mode ActionMode being created + * @param menu Menu used to populate action buttons + * @return true if the action mode should be created, false if entering this + * mode should be aborted. + */ + public boolean onCreateActionMode(ActionMode mode, Menu menu); + + /** + * Called to refresh an action mode's action menu whenever it is invalidated. + * + * @param mode ActionMode being prepared + * @param menu Menu used to populate action buttons + * @return true if the menu or action mode was updated, false otherwise. + */ + public boolean onPrepareActionMode(ActionMode mode, Menu menu); + + /** + * Called to report a user click on an action button. + * + * @param mode The current ActionMode + * @param item The item that was clicked + * @return true if this callback handled the event, false if the standard MenuItem + * invocation should continue. + */ + public boolean onActionItemClicked(ActionMode mode, MenuItem item); + + /** + * Called when an action mode is about to be exited and destroyed. + * + * @param mode The current ActionMode being destroyed + */ + public void onDestroyActionMode(ActionMode mode); + } +} \ No newline at end of file diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java new file mode 100644 index 000000000..ae7cb1fe0 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/ActionProvider.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import android.content.Context; +import android.view.View; + +/** + * This class is a mediator for accomplishing a given task, for example sharing a file. + * It is responsible for creating a view that performs an action that accomplishes the task. + * This class also implements other functions such a performing a default action. + *

+ * An ActionProvider can be optionally specified for a {@link MenuItem} and in such a + * case it will be responsible for creating the action view that appears in the + * {@link android.app.ActionBar} as a substitute for the menu item when the item is + * displayed as an action item. Also the provider is responsible for performing a + * default action if a menu item placed on the overflow menu of the ActionBar is + * selected and none of the menu item callbacks has handled the selection. For this + * case the provider can also optionally provide a sub-menu for accomplishing the + * task at hand. + *

+ *

+ * There are two ways for using an action provider for creating and handling of action views: + *

    + *
  • + * Setting the action provider on a {@link MenuItem} directly by calling + * {@link MenuItem#setActionProvider(ActionProvider)}. + *
  • + *
  • + * Declaring the action provider in the menu XML resource. For example: + *
    + * 
    + *   <item android:id="@+id/my_menu_item"
    + *     android:title="Title"
    + *     android:icon="@drawable/my_menu_item_icon"
    + *     android:showAsAction="ifRoom"
    + *     android:actionProviderClass="foo.bar.SomeActionProvider" />
    + * 
    + * 
    + *
  • + *
+ *

+ * + * @see MenuItem#setActionProvider(ActionProvider) + * @see MenuItem#getActionProvider() + */ +public abstract class ActionProvider { + private SubUiVisibilityListener mSubUiVisibilityListener; + + /** + * Creates a new instance. + * + * @param context Context for accessing resources. + */ + public ActionProvider(Context context) { + } + + /** + * Factory method for creating new action views. + * + * @return A new action view. + */ + public abstract View onCreateActionView(); + + /** + * Performs an optional default action. + *

+ * For the case of an action provider placed in a menu item not shown as an action this + * method is invoked if previous callbacks for processing menu selection has handled + * the event. + *

+ *

+ * A menu item selection is processed in the following order: + *

    + *
  • + * Receiving a call to {@link MenuItem.OnMenuItemClickListener#onMenuItemClick + * MenuItem.OnMenuItemClickListener.onMenuItemClick}. + *
  • + *
  • + * Receiving a call to {@link android.app.Activity#onOptionsItemSelected(MenuItem) + * Activity.onOptionsItemSelected(MenuItem)} + *
  • + *
  • + * Receiving a call to {@link android.app.Fragment#onOptionsItemSelected(MenuItem) + * Fragment.onOptionsItemSelected(MenuItem)} + *
  • + *
  • + * Launching the {@link android.content.Intent} set via + * {@link MenuItem#setIntent(android.content.Intent) MenuItem.setIntent(android.content.Intent)} + *
  • + *
  • + * Invoking this method. + *
  • + *
+ *

+ *

+ * The default implementation does not perform any action and returns false. + *

+ */ + public boolean onPerformDefaultAction() { + return false; + } + + /** + * Determines if this ActionProvider has a submenu associated with it. + * + *

Associated submenus will be shown when an action view is not. This + * provider instance will receive a call to {@link #onPrepareSubMenu(SubMenu)} + * after the call to {@link #onPerformDefaultAction()} and before a submenu is + * displayed to the user. + * + * @return true if the item backed by this provider should have an associated submenu + */ + public boolean hasSubMenu() { + return false; + } + + /** + * Called to prepare an associated submenu for the menu item backed by this ActionProvider. + * + *

if {@link #hasSubMenu()} returns true, this method will be called when the + * menu item is selected to prepare the submenu for presentation to the user. Apps + * may use this to create or alter submenu content right before display. + * + * @param subMenu Submenu that will be displayed + */ + public void onPrepareSubMenu(SubMenu subMenu) { + } + + /** + * Notify the system that the visibility of an action view's sub-UI such as + * an anchored popup has changed. This will affect how other system + * visibility notifications occur. + * + * @hide Pending future API approval + */ + public void subUiVisibilityChanged(boolean isVisible) { + if (mSubUiVisibilityListener != null) { + mSubUiVisibilityListener.onSubUiVisibilityChanged(isVisible); + } + } + + /** + * @hide Internal use only + */ + public void setSubUiVisibilityListener(SubUiVisibilityListener listener) { + mSubUiVisibilityListener = listener; + } + + /** + * @hide Internal use only + */ + public interface SubUiVisibilityListener { + public void onSubUiVisibilityChanged(boolean isVisible); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java new file mode 100644 index 000000000..43281b013 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/CollapsibleActionView.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +/** + * When a {@link View} implements this interface it will receive callbacks + * when expanded or collapsed as an action view alongside the optional, + * app-specified callbacks to {@link OnActionExpandListener}. + * + *

See {@link MenuItem} for more information about action views. + * See {@link android.app.ActionBar} for more information about the action bar. + */ +public interface CollapsibleActionView { + /** + * Called when this view is expanded as an action view. + * See {@link MenuItem#expandActionView()}. + */ + public void onActionViewExpanded(); + + /** + * Called when this view is collapsed as an action view. + * See {@link MenuItem#collapseActionView()}. + */ + public void onActionViewCollapsed(); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java new file mode 100644 index 000000000..951f4ccef --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Menu.java @@ -0,0 +1,447 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import android.content.ComponentName; +import android.content.Intent; +import android.view.KeyEvent; + +/** + * Interface for managing the items in a menu. + *

+ * By default, every Activity supports an options menu of actions or options. + * You can add items to this menu and handle clicks on your additions. The + * easiest way of adding menu items is inflating an XML file into the + * {@link Menu} via {@link MenuInflater}. The easiest way of attaching code to + * clicks is via {@link Activity#onOptionsItemSelected(MenuItem)} and + * {@link Activity#onContextItemSelected(MenuItem)}. + *

+ * Different menu types support different features: + *

    + *
  1. Context menus: Do not support item shortcuts and item icons. + *
  2. Options menus: The icon menus do not support item check + * marks and only show the item's + * {@link MenuItem#setTitleCondensed(CharSequence) condensed title}. The + * expanded menus (only available if six or more menu items are visible, + * reached via the 'More' item in the icon menu) do not show item icons, and + * item check marks are discouraged. + *
  3. Sub menus: Do not support item icons, or nested sub menus. + *
+ * + *
+ *

Developer Guides

+ *

For more information about creating menus, read the + * Menus developer guide.

+ *
+ */ +public interface Menu { + + /** + * This is the part of an order integer that the user can provide. + * @hide + */ + static final int USER_MASK = 0x0000ffff; + /** + * Bit shift of the user portion of the order integer. + * @hide + */ + static final int USER_SHIFT = 0; + + /** + * This is the part of an order integer that supplies the category of the + * item. + * @hide + */ + static final int CATEGORY_MASK = 0xffff0000; + /** + * Bit shift of the category portion of the order integer. + * @hide + */ + static final int CATEGORY_SHIFT = 16; + + /** + * Value to use for group and item identifier integers when you don't care + * about them. + */ + static final int NONE = 0; + + /** + * First value for group and item identifier integers. + */ + static final int FIRST = 1; + + // Implementation note: Keep these CATEGORY_* in sync with the category enum + // in attrs.xml + + /** + * Category code for the order integer for items/groups that are part of a + * container -- or/add this with your base value. + */ + static final int CATEGORY_CONTAINER = 0x00010000; + + /** + * Category code for the order integer for items/groups that are provided by + * the system -- or/add this with your base value. + */ + static final int CATEGORY_SYSTEM = 0x00020000; + + /** + * Category code for the order integer for items/groups that are + * user-supplied secondary (infrequently used) options -- or/add this with + * your base value. + */ + static final int CATEGORY_SECONDARY = 0x00030000; + + /** + * Category code for the order integer for items/groups that are + * alternative actions on the data that is currently displayed -- or/add + * this with your base value. + */ + static final int CATEGORY_ALTERNATIVE = 0x00040000; + + /** + * Flag for {@link #addIntentOptions}: if set, do not automatically remove + * any existing menu items in the same group. + */ + static final int FLAG_APPEND_TO_GROUP = 0x0001; + + /** + * Flag for {@link #performShortcut}: if set, do not close the menu after + * executing the shortcut. + */ + static final int FLAG_PERFORM_NO_CLOSE = 0x0001; + + /** + * Flag for {@link #performShortcut(int, KeyEvent, int)}: if set, always + * close the menu after executing the shortcut. Closing the menu also resets + * the prepared state. + */ + static final int FLAG_ALWAYS_PERFORM_CLOSE = 0x0002; + + /** + * Add a new item to the menu. This item displays the given title for its + * label. + * + * @param title The text to display for the item. + * @return The newly added menu item. + */ + public MenuItem add(CharSequence title); + + /** + * Add a new item to the menu. This item displays the given title for its + * label. + * + * @param titleRes Resource identifier of title string. + * @return The newly added menu item. + */ + public MenuItem add(int titleRes); + + /** + * Add a new item to the menu. This item displays the given title for its + * label. + * + * @param groupId The group identifier that this item should be part of. + * This can be used to define groups of items for batch state + * changes. Normally use {@link #NONE} if an item should not be in a + * group. + * @param itemId Unique item ID. Use {@link #NONE} if you do not need a + * unique ID. + * @param order The order for the item. Use {@link #NONE} if you do not care + * about the order. See {@link MenuItem#getOrder()}. + * @param title The text to display for the item. + * @return The newly added menu item. + */ + public MenuItem add(int groupId, int itemId, int order, CharSequence title); + + /** + * Variation on {@link #add(int, int, int, CharSequence)} that takes a + * string resource identifier instead of the string itself. + * + * @param groupId The group identifier that this item should be part of. + * This can also be used to define groups of items for batch state + * changes. Normally use {@link #NONE} if an item should not be in a + * group. + * @param itemId Unique item ID. Use {@link #NONE} if you do not need a + * unique ID. + * @param order The order for the item. Use {@link #NONE} if you do not care + * about the order. See {@link MenuItem#getOrder()}. + * @param titleRes Resource identifier of title string. + * @return The newly added menu item. + */ + public MenuItem add(int groupId, int itemId, int order, int titleRes); + + /** + * Add a new sub-menu to the menu. This item displays the given title for + * its label. To modify other attributes on the submenu's menu item, use + * {@link SubMenu#getItem()}. + * + * @param title The text to display for the item. + * @return The newly added sub-menu + */ + SubMenu addSubMenu(final CharSequence title); + + /** + * Add a new sub-menu to the menu. This item displays the given title for + * its label. To modify other attributes on the submenu's menu item, use + * {@link SubMenu#getItem()}. + * + * @param titleRes Resource identifier of title string. + * @return The newly added sub-menu + */ + SubMenu addSubMenu(final int titleRes); + + /** + * Add a new sub-menu to the menu. This item displays the given + * title for its label. To modify other attributes on the + * submenu's menu item, use {@link SubMenu#getItem()}. + *

+ * Note that you can only have one level of sub-menus, i.e. you cannnot add + * a subMenu to a subMenu: An {@link UnsupportedOperationException} will be + * thrown if you try. + * + * @param groupId The group identifier that this item should be part of. + * This can also be used to define groups of items for batch state + * changes. Normally use {@link #NONE} if an item should not be in a + * group. + * @param itemId Unique item ID. Use {@link #NONE} if you do not need a + * unique ID. + * @param order The order for the item. Use {@link #NONE} if you do not care + * about the order. See {@link MenuItem#getOrder()}. + * @param title The text to display for the item. + * @return The newly added sub-menu + */ + SubMenu addSubMenu(final int groupId, final int itemId, int order, final CharSequence title); + + /** + * Variation on {@link #addSubMenu(int, int, int, CharSequence)} that takes + * a string resource identifier for the title instead of the string itself. + * + * @param groupId The group identifier that this item should be part of. + * This can also be used to define groups of items for batch state + * changes. Normally use {@link #NONE} if an item should not be in a group. + * @param itemId Unique item ID. Use {@link #NONE} if you do not need a unique ID. + * @param order The order for the item. Use {@link #NONE} if you do not care about the + * order. See {@link MenuItem#getOrder()}. + * @param titleRes Resource identifier of title string. + * @return The newly added sub-menu + */ + SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes); + + /** + * Add a group of menu items corresponding to actions that can be performed + * for a particular Intent. The Intent is most often configured with a null + * action, the data that the current activity is working with, and includes + * either the {@link Intent#CATEGORY_ALTERNATIVE} or + * {@link Intent#CATEGORY_SELECTED_ALTERNATIVE} to find activities that have + * said they would like to be included as optional action. You can, however, + * use any Intent you want. + * + *

+ * See {@link android.content.pm.PackageManager#queryIntentActivityOptions} + * for more * details on the caller, specifics, and + * intent arguments. The list returned by that function is used + * to populate the resulting menu items. + * + *

+ * All of the menu items of possible options for the intent will be added + * with the given group and id. You can use the group to control ordering of + * the items in relation to other items in the menu. Normally this function + * will automatically remove any existing items in the menu in the same + * group and place a divider above and below the added items; this behavior + * can be modified with the flags parameter. For each of the + * generated items {@link MenuItem#setIntent} is called to associate the + * appropriate Intent with the item; this means the activity will + * automatically be started for you without having to do anything else. + * + * @param groupId The group identifier that the items should be part of. + * This can also be used to define groups of items for batch state + * changes. Normally use {@link #NONE} if the items should not be in + * a group. + * @param itemId Unique item ID. Use {@link #NONE} if you do not need a + * unique ID. + * @param order The order for the items. Use {@link #NONE} if you do not + * care about the order. See {@link MenuItem#getOrder()}. + * @param caller The current activity component name as defined by + * queryIntentActivityOptions(). + * @param specifics Specific items to place first as defined by + * queryIntentActivityOptions(). + * @param intent Intent describing the kinds of items to populate in the + * list as defined by queryIntentActivityOptions(). + * @param flags Additional options controlling how the items are added. + * @param outSpecificItems Optional array in which to place the menu items + * that were generated for each of the specifics that were + * requested. Entries may be null if no activity was found for that + * specific action. + * @return The number of menu items that were added. + * + * @see #FLAG_APPEND_TO_GROUP + * @see MenuItem#setIntent + * @see android.content.pm.PackageManager#queryIntentActivityOptions + */ + public int addIntentOptions(int groupId, int itemId, int order, + ComponentName caller, Intent[] specifics, + Intent intent, int flags, MenuItem[] outSpecificItems); + + /** + * Remove the item with the given identifier. + * + * @param id The item to be removed. If there is no item with this + * identifier, nothing happens. + */ + public void removeItem(int id); + + /** + * Remove all items in the given group. + * + * @param groupId The group to be removed. If there are no items in this + * group, nothing happens. + */ + public void removeGroup(int groupId); + + /** + * Remove all existing items from the menu, leaving it empty as if it had + * just been created. + */ + public void clear(); + + /** + * Control whether a particular group of items can show a check mark. This + * is similar to calling {@link MenuItem#setCheckable} on all of the menu items + * with the given group identifier, but in addition you can control whether + * this group contains a mutually-exclusive set items. This should be called + * after the items of the group have been added to the menu. + * + * @param group The group of items to operate on. + * @param checkable Set to true to allow a check mark, false to + * disallow. The default is false. + * @param exclusive If set to true, only one item in this group can be + * checked at a time; checking an item will automatically + * uncheck all others in the group. If set to false, each + * item can be checked independently of the others. + * + * @see MenuItem#setCheckable + * @see MenuItem#setChecked + */ + public void setGroupCheckable(int group, boolean checkable, boolean exclusive); + + /** + * Show or hide all menu items that are in the given group. + * + * @param group The group of items to operate on. + * @param visible If true the items are visible, else they are hidden. + * + * @see MenuItem#setVisible + */ + public void setGroupVisible(int group, boolean visible); + + /** + * Enable or disable all menu items that are in the given group. + * + * @param group The group of items to operate on. + * @param enabled If true the items will be enabled, else they will be disabled. + * + * @see MenuItem#setEnabled + */ + public void setGroupEnabled(int group, boolean enabled); + + /** + * Return whether the menu currently has item items that are visible. + * + * @return True if there is one or more item visible, + * else false. + */ + public boolean hasVisibleItems(); + + /** + * Return the menu item with a particular identifier. + * + * @param id The identifier to find. + * + * @return The menu item object, or null if there is no item with + * this identifier. + */ + public MenuItem findItem(int id); + + /** + * Get the number of items in the menu. Note that this will change any + * times items are added or removed from the menu. + * + * @return The item count. + */ + public int size(); + + /** + * Gets the menu item at the given index. + * + * @param index The index of the menu item to return. + * @return The menu item. + * @exception IndexOutOfBoundsException + * when {@code index < 0 || >= size()} + */ + public MenuItem getItem(int index); + + /** + * Closes the menu, if open. + */ + public void close(); + + /** + * Execute the menu item action associated with the given shortcut + * character. + * + * @param keyCode The keycode of the shortcut key. + * @param event Key event message. + * @param flags Additional option flags or 0. + * + * @return If the given shortcut exists and is shown, returns + * true; else returns false. + * + * @see #FLAG_PERFORM_NO_CLOSE + */ + public boolean performShortcut(int keyCode, KeyEvent event, int flags); + + /** + * Is a keypress one of the defined shortcut keys for this window. + * @param keyCode the key code from {@link KeyEvent} to check. + * @param event the {@link KeyEvent} to use to help check. + */ + boolean isShortcutKey(int keyCode, KeyEvent event); + + /** + * Execute the menu item action associated with the given menu identifier. + * + * @param id Identifier associated with the menu item. + * @param flags Additional option flags or 0. + * + * @return If the given identifier exists and is shown, returns + * true; else returns false. + * + * @see #FLAG_PERFORM_NO_CLOSE + */ + public boolean performIdentifierAction(int id, int flags); + + + /** + * Control whether the menu should be running in qwerty mode (alphabetic + * shortcuts) or 12-key mode (numeric shortcuts). + * + * @param isQwerty If true the menu will use alphabetic shortcuts; else it + * will use numeric shortcuts. + */ + public void setQwertyMode(boolean isQwerty); +} + diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java new file mode 100644 index 000000000..5a0f40859 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuInflater.java @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * 2011 Jake Wharton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import android.content.Context; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.util.Xml; +import android.view.InflateException; +import android.view.View; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.view.menu.MenuItemImpl; + +/** + * This class is used to instantiate menu XML files into Menu objects. + *

+ * For performance reasons, menu inflation relies heavily on pre-processing of + * XML files that is done at build time. Therefore, it is not currently possible + * to use MenuInflater with an XmlPullParser over a plain XML file at runtime; + * it only works with an XmlPullParser returned from a compiled resource (R. + * something file.) + */ +public class MenuInflater { + private static final String LOG_TAG = "MenuInflater"; + + /** Menu tag name in XML. */ + private static final String XML_MENU = "menu"; + + /** Group tag name in XML. */ + private static final String XML_GROUP = "group"; + + /** Item tag name in XML. */ + private static final String XML_ITEM = "item"; + + private static final int NO_ID = 0; + + private static final Class[] ACTION_VIEW_CONSTRUCTOR_SIGNATURE = new Class[] {Context.class}; + + private static final Class[] ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE = ACTION_VIEW_CONSTRUCTOR_SIGNATURE; + + private final Object[] mActionViewConstructorArguments; + + private final Object[] mActionProviderConstructorArguments; + + private Context mContext; + private Object mRealOwner; + + /** + * Constructs a menu inflater. + * + * @see Activity#getMenuInflater() + */ + public MenuInflater(Context context) { + mContext = context; + mRealOwner = context; + mActionViewConstructorArguments = new Object[] {context}; + mActionProviderConstructorArguments = mActionViewConstructorArguments; + } + + /** + * Constructs a menu inflater. + * + * @see Activity#getMenuInflater() + * @hide + */ + public MenuInflater(Context context, Object realOwner) { + mContext = context; + mRealOwner = realOwner; + mActionViewConstructorArguments = new Object[] {context}; + mActionProviderConstructorArguments = mActionViewConstructorArguments; + } + + /** + * Inflate a menu hierarchy from the specified XML resource. Throws + * {@link InflateException} if there is an error. + * + * @param menuRes Resource ID for an XML layout resource to load (e.g., + * R.menu.main_activity) + * @param menu The Menu to inflate into. The items and submenus will be + * added to this Menu. + */ + public void inflate(int menuRes, Menu menu) { + XmlResourceParser parser = null; + try { + parser = mContext.getResources().getLayout(menuRes); + AttributeSet attrs = Xml.asAttributeSet(parser); + + parseMenu(parser, attrs, menu); + } catch (XmlPullParserException e) { + throw new InflateException("Error inflating menu XML", e); + } catch (IOException e) { + throw new InflateException("Error inflating menu XML", e); + } finally { + if (parser != null) parser.close(); + } + } + + /** + * Called internally to fill the given menu. If a sub menu is seen, it will + * call this recursively. + */ + private void parseMenu(XmlPullParser parser, AttributeSet attrs, Menu menu) + throws XmlPullParserException, IOException { + MenuState menuState = new MenuState(menu); + + int eventType = parser.getEventType(); + String tagName; + boolean lookingForEndOfUnknownTag = false; + String unknownTagName = null; + + // This loop will skip to the menu start tag + do { + if (eventType == XmlPullParser.START_TAG) { + tagName = parser.getName(); + if (tagName.equals(XML_MENU)) { + // Go to next tag + eventType = parser.next(); + break; + } + + throw new RuntimeException("Expecting menu, got " + tagName); + } + eventType = parser.next(); + } while (eventType != XmlPullParser.END_DOCUMENT); + + boolean reachedEndOfMenu = false; + while (!reachedEndOfMenu) { + switch (eventType) { + case XmlPullParser.START_TAG: + if (lookingForEndOfUnknownTag) { + break; + } + + tagName = parser.getName(); + if (tagName.equals(XML_GROUP)) { + menuState.readGroup(attrs); + } else if (tagName.equals(XML_ITEM)) { + menuState.readItem(attrs); + } else if (tagName.equals(XML_MENU)) { + // A menu start tag denotes a submenu for an item + SubMenu subMenu = menuState.addSubMenuItem(); + + // Parse the submenu into returned SubMenu + parseMenu(parser, attrs, subMenu); + } else { + lookingForEndOfUnknownTag = true; + unknownTagName = tagName; + } + break; + + case XmlPullParser.END_TAG: + tagName = parser.getName(); + if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) { + lookingForEndOfUnknownTag = false; + unknownTagName = null; + } else if (tagName.equals(XML_GROUP)) { + menuState.resetGroup(); + } else if (tagName.equals(XML_ITEM)) { + // Add the item if it hasn't been added (if the item was + // a submenu, it would have been added already) + if (!menuState.hasAddedItem()) { + if (menuState.itemActionProvider != null && + menuState.itemActionProvider.hasSubMenu()) { + menuState.addSubMenuItem(); + } else { + menuState.addItem(); + } + } + } else if (tagName.equals(XML_MENU)) { + reachedEndOfMenu = true; + } + break; + + case XmlPullParser.END_DOCUMENT: + throw new RuntimeException("Unexpected end of document"); + } + + eventType = parser.next(); + } + } + + private static class InflatedOnMenuItemClickListener + implements MenuItem.OnMenuItemClickListener { + private static final Class[] PARAM_TYPES = new Class[] { MenuItem.class }; + + private Object mRealOwner; + private Method mMethod; + + public InflatedOnMenuItemClickListener(Object realOwner, String methodName) { + mRealOwner = realOwner; + Class c = realOwner.getClass(); + try { + mMethod = c.getMethod(methodName, PARAM_TYPES); + } catch (Exception e) { + InflateException ex = new InflateException( + "Couldn't resolve menu item onClick handler " + methodName + + " in class " + c.getName()); + ex.initCause(e); + throw ex; + } + } + + public boolean onMenuItemClick(MenuItem item) { + try { + if (mMethod.getReturnType() == Boolean.TYPE) { + return (Boolean) mMethod.invoke(mRealOwner, item); + } else { + mMethod.invoke(mRealOwner, item); + return true; + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + /** + * State for the current menu. + *

+ * Groups can not be nested unless there is another menu (which will have + * its state class). + */ + private class MenuState { + private Menu menu; + + /* + * Group state is set on items as they are added, allowing an item to + * override its group state. (As opposed to set on items at the group end tag.) + */ + private int groupId; + private int groupCategory; + private int groupOrder; + private int groupCheckable; + private boolean groupVisible; + private boolean groupEnabled; + + private boolean itemAdded; + private int itemId; + private int itemCategoryOrder; + private CharSequence itemTitle; + private CharSequence itemTitleCondensed; + private int itemIconResId; + private char itemAlphabeticShortcut; + private char itemNumericShortcut; + /** + * Sync to attrs.xml enum: + * - 0: none + * - 1: all + * - 2: exclusive + */ + private int itemCheckable; + private boolean itemChecked; + private boolean itemVisible; + private boolean itemEnabled; + + /** + * Sync to attrs.xml enum, values in MenuItem: + * - 0: never + * - 1: ifRoom + * - 2: always + * - -1: Safe sentinel for "no value". + */ + private int itemShowAsAction; + + private int itemActionViewLayout; + private String itemActionViewClassName; + private String itemActionProviderClassName; + + private String itemListenerMethodName; + + private ActionProvider itemActionProvider; + + private static final int defaultGroupId = NO_ID; + private static final int defaultItemId = NO_ID; + private static final int defaultItemCategory = 0; + private static final int defaultItemOrder = 0; + private static final int defaultItemCheckable = 0; + private static final boolean defaultItemChecked = false; + private static final boolean defaultItemVisible = true; + private static final boolean defaultItemEnabled = true; + + public MenuState(final Menu menu) { + this.menu = menu; + + resetGroup(); + } + + public void resetGroup() { + groupId = defaultGroupId; + groupCategory = defaultItemCategory; + groupOrder = defaultItemOrder; + groupCheckable = defaultItemCheckable; + groupVisible = defaultItemVisible; + groupEnabled = defaultItemEnabled; + } + + /** + * Called when the parser is pointing to a group tag. + */ + public void readGroup(AttributeSet attrs) { + TypedArray a = mContext.obtainStyledAttributes(attrs, + R.styleable.SherlockMenuGroup); + + groupId = a.getResourceId(R.styleable.SherlockMenuGroup_android_id, defaultGroupId); + groupCategory = a.getInt(R.styleable.SherlockMenuGroup_android_menuCategory, defaultItemCategory); + groupOrder = a.getInt(R.styleable.SherlockMenuGroup_android_orderInCategory, defaultItemOrder); + groupCheckable = a.getInt(R.styleable.SherlockMenuGroup_android_checkableBehavior, defaultItemCheckable); + groupVisible = a.getBoolean(R.styleable.SherlockMenuGroup_android_visible, defaultItemVisible); + groupEnabled = a.getBoolean(R.styleable.SherlockMenuGroup_android_enabled, defaultItemEnabled); + + a.recycle(); + } + + /** + * Called when the parser is pointing to an item tag. + */ + public void readItem(AttributeSet attrs) { + TypedArray a = mContext.obtainStyledAttributes(attrs, + R.styleable.SherlockMenuItem); + + // Inherit attributes from the group as default value + itemId = a.getResourceId(R.styleable.SherlockMenuItem_android_id, defaultItemId); + final int category = a.getInt(R.styleable.SherlockMenuItem_android_menuCategory, groupCategory); + final int order = a.getInt(R.styleable.SherlockMenuItem_android_orderInCategory, groupOrder); + itemCategoryOrder = (category & Menu.CATEGORY_MASK) | (order & Menu.USER_MASK); + itemTitle = a.getText(R.styleable.SherlockMenuItem_android_title); + itemTitleCondensed = a.getText(R.styleable.SherlockMenuItem_android_titleCondensed); + itemIconResId = a.getResourceId(R.styleable.SherlockMenuItem_android_icon, 0); + itemAlphabeticShortcut = + getShortcut(a.getString(R.styleable.SherlockMenuItem_android_alphabeticShortcut)); + itemNumericShortcut = + getShortcut(a.getString(R.styleable.SherlockMenuItem_android_numericShortcut)); + if (a.hasValue(R.styleable.SherlockMenuItem_android_checkable)) { + // Item has attribute checkable, use it + itemCheckable = a.getBoolean(R.styleable.SherlockMenuItem_android_checkable, false) ? 1 : 0; + } else { + // Item does not have attribute, use the group's (group can have one more state + // for checkable that represents the exclusive checkable) + itemCheckable = groupCheckable; + } + + itemChecked = a.getBoolean(R.styleable.SherlockMenuItem_android_checked, defaultItemChecked); + itemVisible = a.getBoolean(R.styleable.SherlockMenuItem_android_visible, groupVisible); + itemEnabled = a.getBoolean(R.styleable.SherlockMenuItem_android_enabled, groupEnabled); + + TypedValue value = new TypedValue(); + a.getValue(R.styleable.SherlockMenuItem_android_showAsAction, value); + itemShowAsAction = value.type == TypedValue.TYPE_INT_HEX ? value.data : -1; + + itemListenerMethodName = a.getString(R.styleable.SherlockMenuItem_android_onClick); + itemActionViewLayout = a.getResourceId(R.styleable.SherlockMenuItem_android_actionLayout, 0); + + // itemActionViewClassName = a.getString(R.styleable.SherlockMenuItem_android_actionViewClass); + value = new TypedValue(); + a.getValue(R.styleable.SherlockMenuItem_android_actionViewClass, value); + itemActionViewClassName = value.type == TypedValue.TYPE_STRING ? value.string.toString() : null; + + // itemActionProviderClassName = a.getString(R.styleable.SherlockMenuItem_android_actionProviderClass); + value = new TypedValue(); + a.getValue(R.styleable.SherlockMenuItem_android_actionProviderClass, value); + itemActionProviderClassName = value.type == TypedValue.TYPE_STRING ? value.string.toString() : null; + + final boolean hasActionProvider = itemActionProviderClassName != null; + if (hasActionProvider && itemActionViewLayout == 0 && itemActionViewClassName == null) { + itemActionProvider = newInstance(itemActionProviderClassName, + ACTION_PROVIDER_CONSTRUCTOR_SIGNATURE, + mActionProviderConstructorArguments); + } else { + if (hasActionProvider) { + Log.w(LOG_TAG, "Ignoring attribute 'actionProviderClass'." + + " Action view already specified."); + } + itemActionProvider = null; + } + + a.recycle(); + + itemAdded = false; + } + + private char getShortcut(String shortcutString) { + if (shortcutString == null) { + return 0; + } else { + return shortcutString.charAt(0); + } + } + + private void setItem(MenuItem item) { + item.setChecked(itemChecked) + .setVisible(itemVisible) + .setEnabled(itemEnabled) + .setCheckable(itemCheckable >= 1) + .setTitleCondensed(itemTitleCondensed) + .setIcon(itemIconResId) + .setAlphabeticShortcut(itemAlphabeticShortcut) + .setNumericShortcut(itemNumericShortcut); + + if (itemShowAsAction >= 0) { + item.setShowAsAction(itemShowAsAction); + } + + if (itemListenerMethodName != null) { + if (mContext.isRestricted()) { + throw new IllegalStateException("The android:onClick attribute cannot " + + "be used within a restricted context"); + } + item.setOnMenuItemClickListener( + new InflatedOnMenuItemClickListener(mRealOwner, itemListenerMethodName)); + } + + if (itemCheckable >= 2) { + if (item instanceof MenuItemImpl) { + MenuItemImpl impl = (MenuItemImpl) item; + impl.setExclusiveCheckable(true); + } else { + menu.setGroupCheckable(groupId, true, true); + } + } + + boolean actionViewSpecified = false; + if (itemActionViewClassName != null) { + View actionView = (View) newInstance(itemActionViewClassName, + ACTION_VIEW_CONSTRUCTOR_SIGNATURE, mActionViewConstructorArguments); + item.setActionView(actionView); + actionViewSpecified = true; + } + if (itemActionViewLayout > 0) { + if (!actionViewSpecified) { + item.setActionView(itemActionViewLayout); + actionViewSpecified = true; + } else { + Log.w(LOG_TAG, "Ignoring attribute 'itemActionViewLayout'." + + " Action view already specified."); + } + } + if (itemActionProvider != null) { + item.setActionProvider(itemActionProvider); + } + } + + public void addItem() { + itemAdded = true; + setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle)); + } + + public SubMenu addSubMenuItem() { + itemAdded = true; + SubMenu subMenu = menu.addSubMenu(groupId, itemId, itemCategoryOrder, itemTitle); + setItem(subMenu.getItem()); + return subMenu; + } + + public boolean hasAddedItem() { + return itemAdded; + } + + @SuppressWarnings("unchecked") + private T newInstance(String className, Class[] constructorSignature, + Object[] arguments) { + try { + Class clazz = mContext.getClassLoader().loadClass(className); + Constructor constructor = clazz.getConstructor(constructorSignature); + return (T) constructor.newInstance(arguments); + } catch (Exception e) { + Log.w(LOG_TAG, "Cannot instantiate class: " + className, e); + } + return null; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java new file mode 100644 index 000000000..7fc3aa430 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/MenuItem.java @@ -0,0 +1,598 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.View; + +/** + * Interface for direct access to a previously created menu item. + *

+ * An Item is returned by calling one of the {@link android.view.Menu#add} + * methods. + *

+ * For a feature set of specific menu types, see {@link Menu}. + * + *

+ *

Developer Guides

+ *

For information about creating menus, read the + * Menus developer guide.

+ *
+ */ +public interface MenuItem { + /* + * These should be kept in sync with attrs.xml enum constants for showAsAction + */ + /** Never show this item as a button in an Action Bar. */ + public static final int SHOW_AS_ACTION_NEVER = android.view.MenuItem.SHOW_AS_ACTION_NEVER; + /** Show this item as a button in an Action Bar if the system decides there is room for it. */ + public static final int SHOW_AS_ACTION_IF_ROOM = android.view.MenuItem.SHOW_AS_ACTION_IF_ROOM; + /** + * Always show this item as a button in an Action Bar. + * Use sparingly! If too many items are set to always show in the Action Bar it can + * crowd the Action Bar and degrade the user experience on devices with smaller screens. + * A good rule of thumb is to have no more than 2 items set to always show at a time. + */ + public static final int SHOW_AS_ACTION_ALWAYS = android.view.MenuItem.SHOW_AS_ACTION_ALWAYS; + + /** + * When this item is in the action bar, always show it with a text label even if + * it also has an icon specified. + */ + public static final int SHOW_AS_ACTION_WITH_TEXT = android.view.MenuItem.SHOW_AS_ACTION_WITH_TEXT; + + /** + * This item's action view collapses to a normal menu item. + * When expanded, the action view temporarily takes over + * a larger segment of its container. + */ + public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = android.view.MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW; + + /** + * Interface definition for a callback to be invoked when a menu item is + * clicked. + * + * @see Activity#onContextItemSelected(MenuItem) + * @see Activity#onOptionsItemSelected(MenuItem) + */ + public interface OnMenuItemClickListener { + /** + * Called when a menu item has been invoked. This is the first code + * that is executed; if it returns true, no other callbacks will be + * executed. + * + * @param item The menu item that was invoked. + * + * @return Return true to consume this click and prevent others from + * executing. + */ + public boolean onMenuItemClick(MenuItem item); + } + + /** + * Interface definition for a callback to be invoked when a menu item + * marked with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} is + * expanded or collapsed. + * + * @see MenuItem#expandActionView() + * @see MenuItem#collapseActionView() + * @see MenuItem#setShowAsActionFlags(int) + */ + public interface OnActionExpandListener { + /** + * Called when a menu item with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} + * is expanded. + * @param item Item that was expanded + * @return true if the item should expand, false if expansion should be suppressed. + */ + public boolean onMenuItemActionExpand(MenuItem item); + + /** + * Called when a menu item with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} + * is collapsed. + * @param item Item that was collapsed + * @return true if the item should collapse, false if collapsing should be suppressed. + */ + public boolean onMenuItemActionCollapse(MenuItem item); + } + + /** + * Return the identifier for this menu item. The identifier can not + * be changed after the menu is created. + * + * @return The menu item's identifier. + */ + public int getItemId(); + + /** + * Return the group identifier that this menu item is part of. The group + * identifier can not be changed after the menu is created. + * + * @return The menu item's group identifier. + */ + public int getGroupId(); + + /** + * Return the category and order within the category of this item. This + * item will be shown before all items (within its category) that have + * order greater than this value. + *

+ * An order integer contains the item's category (the upper bits of the + * integer; set by or/add the category with the order within the + * category) and the ordering of the item within that category (the + * lower bits). Example categories are {@link Menu#CATEGORY_SYSTEM}, + * {@link Menu#CATEGORY_SECONDARY}, {@link Menu#CATEGORY_ALTERNATIVE}, + * {@link Menu#CATEGORY_CONTAINER}. See {@link Menu} for a full list. + * + * @return The order of this item. + */ + public int getOrder(); + + /** + * Change the title associated with this item. + * + * @param title The new text to be displayed. + * @return This Item so additional setters can be called. + */ + public MenuItem setTitle(CharSequence title); + + /** + * Change the title associated with this item. + *

+ * Some menu types do not sufficient space to show the full title, and + * instead a condensed title is preferred. See {@link Menu} for more + * information. + * + * @param title The resource id of the new text to be displayed. + * @return This Item so additional setters can be called. + * @see #setTitleCondensed(CharSequence) + */ + + public MenuItem setTitle(int title); + + /** + * Retrieve the current title of the item. + * + * @return The title. + */ + public CharSequence getTitle(); + + /** + * Change the condensed title associated with this item. The condensed + * title is used in situations where the normal title may be too long to + * be displayed. + * + * @param title The new text to be displayed as the condensed title. + * @return This Item so additional setters can be called. + */ + public MenuItem setTitleCondensed(CharSequence title); + + /** + * Retrieve the current condensed title of the item. If a condensed + * title was never set, it will return the normal title. + * + * @return The condensed title, if it exists. + * Otherwise the normal title. + */ + public CharSequence getTitleCondensed(); + + /** + * Change the icon associated with this item. This icon will not always be + * shown, so the title should be sufficient in describing this item. See + * {@link Menu} for the menu types that support icons. + * + * @param icon The new icon (as a Drawable) to be displayed. + * @return This Item so additional setters can be called. + */ + public MenuItem setIcon(Drawable icon); + + /** + * Change the icon associated with this item. This icon will not always be + * shown, so the title should be sufficient in describing this item. See + * {@link Menu} for the menu types that support icons. + *

+ * This method will set the resource ID of the icon which will be used to + * lazily get the Drawable when this item is being shown. + * + * @param iconRes The new icon (as a resource ID) to be displayed. + * @return This Item so additional setters can be called. + */ + public MenuItem setIcon(int iconRes); + + /** + * Returns the icon for this item as a Drawable (getting it from resources if it hasn't been + * loaded before). + * + * @return The icon as a Drawable. + */ + public Drawable getIcon(); + + /** + * Change the Intent associated with this item. By default there is no + * Intent associated with a menu item. If you set one, and nothing + * else handles the item, then the default behavior will be to call + * {@link android.content.Context#startActivity} with the given Intent. + * + *

Note that setIntent() can not be used with the versions of + * {@link Menu#add} that take a Runnable, because {@link Runnable#run} + * does not return a value so there is no way to tell if it handled the + * item. In this case it is assumed that the Runnable always handles + * the item, and the intent will never be started. + * + * @see #getIntent + * @param intent The Intent to associated with the item. This Intent + * object is not copied, so be careful not to + * modify it later. + * @return This Item so additional setters can be called. + */ + public MenuItem setIntent(Intent intent); + + /** + * Return the Intent associated with this item. This returns a + * reference to the Intent which you can change as desired to modify + * what the Item is holding. + * + * @see #setIntent + * @return Returns the last value supplied to {@link #setIntent}, or + * null. + */ + public Intent getIntent(); + + /** + * Change both the numeric and alphabetic shortcut associated with this + * item. Note that the shortcut will be triggered when the key that + * generates the given character is pressed alone or along with with the alt + * key. Also note that case is not significant and that alphabetic shortcut + * characters will be displayed in lower case. + *

+ * See {@link Menu} for the menu types that support shortcuts. + * + * @param numericChar The numeric shortcut key. This is the shortcut when + * using a numeric (e.g., 12-key) keyboard. + * @param alphaChar The alphabetic shortcut key. This is the shortcut when + * using a keyboard with alphabetic keys. + * @return This Item so additional setters can be called. + */ + public MenuItem setShortcut(char numericChar, char alphaChar); + + /** + * Change the numeric shortcut associated with this item. + *

+ * See {@link Menu} for the menu types that support shortcuts. + * + * @param numericChar The numeric shortcut key. This is the shortcut when + * using a 12-key (numeric) keyboard. + * @return This Item so additional setters can be called. + */ + public MenuItem setNumericShortcut(char numericChar); + + /** + * Return the char for this menu item's numeric (12-key) shortcut. + * + * @return Numeric character to use as a shortcut. + */ + public char getNumericShortcut(); + + /** + * Change the alphabetic shortcut associated with this item. The shortcut + * will be triggered when the key that generates the given character is + * pressed alone or along with with the alt key. Case is not significant and + * shortcut characters will be displayed in lower case. Note that menu items + * with the characters '\b' or '\n' as shortcuts will get triggered by the + * Delete key or Carriage Return key, respectively. + *

+ * See {@link Menu} for the menu types that support shortcuts. + * + * @param alphaChar The alphabetic shortcut key. This is the shortcut when + * using a keyboard with alphabetic keys. + * @return This Item so additional setters can be called. + */ + public MenuItem setAlphabeticShortcut(char alphaChar); + + /** + * Return the char for this menu item's alphabetic shortcut. + * + * @return Alphabetic character to use as a shortcut. + */ + public char getAlphabeticShortcut(); + + /** + * Control whether this item can display a check mark. Setting this does + * not actually display a check mark (see {@link #setChecked} for that); + * rather, it ensures there is room in the item in which to display a + * check mark. + *

+ * See {@link Menu} for the menu types that support check marks. + * + * @param checkable Set to true to allow a check mark, false to + * disallow. The default is false. + * @see #setChecked + * @see #isCheckable + * @see Menu#setGroupCheckable + * @return This Item so additional setters can be called. + */ + public MenuItem setCheckable(boolean checkable); + + /** + * Return whether the item can currently display a check mark. + * + * @return If a check mark can be displayed, returns true. + * + * @see #setCheckable + */ + public boolean isCheckable(); + + /** + * Control whether this item is shown with a check mark. Note that you + * must first have enabled checking with {@link #setCheckable} or else + * the check mark will not appear. If this item is a member of a group that contains + * mutually-exclusive items (set via {@link Menu#setGroupCheckable(int, boolean, boolean)}, + * the other items in the group will be unchecked. + *

+ * See {@link Menu} for the menu types that support check marks. + * + * @see #setCheckable + * @see #isChecked + * @see Menu#setGroupCheckable + * @param checked Set to true to display a check mark, false to hide + * it. The default value is false. + * @return This Item so additional setters can be called. + */ + public MenuItem setChecked(boolean checked); + + /** + * Return whether the item is currently displaying a check mark. + * + * @return If a check mark is displayed, returns true. + * + * @see #setChecked + */ + public boolean isChecked(); + + /** + * Sets the visibility of the menu item. Even if a menu item is not visible, + * it may still be invoked via its shortcut (to completely disable an item, + * set it to invisible and {@link #setEnabled(boolean) disabled}). + * + * @param visible If true then the item will be visible; if false it is + * hidden. + * @return This Item so additional setters can be called. + */ + public MenuItem setVisible(boolean visible); + + /** + * Return the visibility of the menu item. + * + * @return If true the item is visible; else it is hidden. + */ + public boolean isVisible(); + + /** + * Sets whether the menu item is enabled. Disabling a menu item will not + * allow it to be invoked via its shortcut. The menu item will still be + * visible. + * + * @param enabled If true then the item will be invokable; if false it is + * won't be invokable. + * @return This Item so additional setters can be called. + */ + public MenuItem setEnabled(boolean enabled); + + /** + * Return the enabled state of the menu item. + * + * @return If true the item is enabled and hence invokable; else it is not. + */ + public boolean isEnabled(); + + /** + * Check whether this item has an associated sub-menu. I.e. it is a + * sub-menu of another menu. + * + * @return If true this item has a menu; else it is a + * normal item. + */ + public boolean hasSubMenu(); + + /** + * Get the sub-menu to be invoked when this item is selected, if it has + * one. See {@link #hasSubMenu()}. + * + * @return The associated menu if there is one, else null + */ + public SubMenu getSubMenu(); + + /** + * Set a custom listener for invocation of this menu item. In most + * situations, it is more efficient and easier to use + * {@link Activity#onOptionsItemSelected(MenuItem)} or + * {@link Activity#onContextItemSelected(MenuItem)}. + * + * @param menuItemClickListener The object to receive invokations. + * @return This Item so additional setters can be called. + * @see Activity#onOptionsItemSelected(MenuItem) + * @see Activity#onContextItemSelected(MenuItem) + */ + public MenuItem setOnMenuItemClickListener(MenuItem.OnMenuItemClickListener menuItemClickListener); + + /** + * Gets the extra information linked to this menu item. This extra + * information is set by the View that added this menu item to the + * menu. + * + * @see OnCreateContextMenuListener + * @return The extra information linked to the View that added this + * menu item to the menu. This can be null. + */ + public ContextMenuInfo getMenuInfo(); + + /** + * Sets how this item should display in the presence of an Action Bar. + * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS}, + * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should + * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}. + * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action, + * it should be shown with a text label. + * + * @param actionEnum How the item should display. One of + * {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or + * {@link #SHOW_AS_ACTION_NEVER}. SHOW_AS_ACTION_NEVER is the default. + * + * @see android.app.ActionBar + * @see #setActionView(View) + */ + public void setShowAsAction(int actionEnum); + + /** + * Sets how this item should display in the presence of an Action Bar. + * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS}, + * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should + * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}. + * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action, + * it should be shown with a text label. + * + *

Note: This method differs from {@link #setShowAsAction(int)} only in that it + * returns the current MenuItem instance for call chaining. + * + * @param actionEnum How the item should display. One of + * {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or + * {@link #SHOW_AS_ACTION_NEVER}. SHOW_AS_ACTION_NEVER is the default. + * + * @see android.app.ActionBar + * @see #setActionView(View) + * @return This MenuItem instance for call chaining. + */ + public MenuItem setShowAsActionFlags(int actionEnum); + + /** + * Set an action view for this menu item. An action view will be displayed in place + * of an automatically generated menu item element in the UI when this item is shown + * as an action within a parent. + *

+ * Note: Setting an action view overrides the action provider + * set via {@link #setActionProvider(ActionProvider)}. + *

+ * + * @param view View to use for presenting this item to the user. + * @return This Item so additional setters can be called. + * + * @see #setShowAsAction(int) + */ + public MenuItem setActionView(View view); + + /** + * Set an action view for this menu item. An action view will be displayed in place + * of an automatically generated menu item element in the UI when this item is shown + * as an action within a parent. + *

+ * Note: Setting an action view overrides the action provider + * set via {@link #setActionProvider(ActionProvider)}. + *

+ * + * @param resId Layout resource to use for presenting this item to the user. + * @return This Item so additional setters can be called. + * + * @see #setShowAsAction(int) + */ + public MenuItem setActionView(int resId); + + /** + * Returns the currently set action view for this menu item. + * + * @return This item's action view + * + * @see #setActionView(View) + * @see #setShowAsAction(int) + */ + public View getActionView(); + + /** + * Sets the {@link ActionProvider} responsible for creating an action view if + * the item is placed on the action bar. The provider also provides a default + * action invoked if the item is placed in the overflow menu. + *

+ * Note: Setting an action provider overrides the action view + * set via {@link #setActionView(int)} or {@link #setActionView(View)}. + *

+ * + * @param actionProvider The action provider. + * @return This Item so additional setters can be called. + * + * @see ActionProvider + */ + public MenuItem setActionProvider(ActionProvider actionProvider); + + /** + * Gets the {@link ActionProvider}. + * + * @return The action provider. + * + * @see ActionProvider + * @see #setActionProvider(ActionProvider) + */ + public ActionProvider getActionProvider(); + + /** + * Expand the action view associated with this menu item. + * The menu item must have an action view set, as well as + * the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. + * If a listener has been set using {@link #setOnActionExpandListener(OnActionExpandListener)} + * it will have its {@link OnActionExpandListener#onMenuItemActionExpand(MenuItem)} + * method invoked. The listener may return false from this method to prevent expanding + * the action view. + * + * @return true if the action view was expanded, false otherwise. + */ + public boolean expandActionView(); + + /** + * Collapse the action view associated with this menu item. + * The menu item must have an action view set, as well as the showAsAction flag + * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. If a listener has been set using + * {@link #setOnActionExpandListener(OnActionExpandListener)} it will have its + * {@link OnActionExpandListener#onMenuItemActionCollapse(MenuItem)} method invoked. + * The listener may return false from this method to prevent collapsing the action view. + * + * @return true if the action view was collapsed, false otherwise. + */ + public boolean collapseActionView(); + + /** + * Returns true if this menu item's action view has been expanded. + * + * @return true if the item's action view is expanded, false otherwise. + * + * @see #expandActionView() + * @see #collapseActionView() + * @see #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW + * @see OnActionExpandListener + */ + public boolean isActionViewExpanded(); + + /** + * Set an {@link OnActionExpandListener} on this menu item to be notified when + * the associated action view is expanded or collapsed. The menu item must + * be configured to expand or collapse its action view using the flag + * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. + * + * @param listener Listener that will respond to expand/collapse events + * @return This menu item instance for call chaining + */ + public MenuItem setOnActionExpandListener(OnActionExpandListener listener); +} \ No newline at end of file diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java new file mode 100644 index 000000000..397fd1c2d --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/SubMenu.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import android.graphics.drawable.Drawable; +import android.view.View; + +/** + * Subclass of {@link Menu} for sub menus. + *

+ * Sub menus do not support item icons, or nested sub menus. + * + *

+ *

Developer Guides

+ *

For information about creating menus, read the + * Menus developer guide.

+ *
+ */ + +public interface SubMenu extends Menu { + /** + * Sets the submenu header's title to the title given in titleRes + * resource identifier. + * + * @param titleRes The string resource identifier used for the title. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setHeaderTitle(int titleRes); + + /** + * Sets the submenu header's title to the title given in title. + * + * @param title The character sequence used for the title. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setHeaderTitle(CharSequence title); + + /** + * Sets the submenu header's icon to the icon given in iconRes + * resource id. + * + * @param iconRes The resource identifier used for the icon. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setHeaderIcon(int iconRes); + + /** + * Sets the submenu header's icon to the icon given in icon + * {@link Drawable}. + * + * @param icon The {@link Drawable} used for the icon. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setHeaderIcon(Drawable icon); + + /** + * Sets the header of the submenu to the {@link View} given in + * view. This replaces the header title and icon (and those + * replace this). + * + * @param view The {@link View} used for the header. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setHeaderView(View view); + + /** + * Clears the header of the submenu. + */ + public void clearHeader(); + + /** + * Change the icon associated with this submenu's item in its parent menu. + * + * @see MenuItem#setIcon(int) + * @param iconRes The new icon (as a resource ID) to be displayed. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setIcon(int iconRes); + + /** + * Change the icon associated with this submenu's item in its parent menu. + * + * @see MenuItem#setIcon(Drawable) + * @param icon The new icon (as a Drawable) to be displayed. + * @return This SubMenu so additional setters can be called. + */ + public SubMenu setIcon(Drawable icon); + + /** + * Gets the {@link MenuItem} that represents this submenu in the parent + * menu. Use this for setting additional item attributes. + * + * @return The {@link MenuItem} that launches the submenu when invoked. + */ + public MenuItem getItem(); +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java new file mode 100644 index 000000000..a340a4291 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/view/Window.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2011 Jake Wharton + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.view; + +import android.content.Context; + +/** + *

Abstract base class for a top-level window look and behavior policy. An + * instance of this class should be used as the top-level view added to the + * window manager. It provides standard UI policies such as a background, title + * area, default key processing, etc.

+ * + *

The only existing implementation of this abstract class is + * android.policy.PhoneWindow, which you should instantiate when needing a + * Window. Eventually that class will be refactored and a factory method added + * for creating Window instances without knowing about a particular + * implementation.

+ */ +public abstract class Window extends android.view.Window { + public static final long FEATURE_ACTION_BAR = android.view.Window.FEATURE_ACTION_BAR; + public static final long FEATURE_ACTION_BAR_OVERLAY = android.view.Window.FEATURE_ACTION_BAR_OVERLAY; + public static final long FEATURE_ACTION_MODE_OVERLAY = android.view.Window.FEATURE_ACTION_MODE_OVERLAY; + public static final long FEATURE_NO_TITLE = android.view.Window.FEATURE_NO_TITLE; + public static final long FEATURE_PROGRESS = android.view.Window.FEATURE_PROGRESS; + public static final long FEATURE_INDETERMINATE_PROGRESS = android.view.Window.FEATURE_INDETERMINATE_PROGRESS; + + /** + * Create a new instance for a context. + * + * @param context Context. + */ + private Window(Context context) { + super(context); + } + + + public interface Callback { + /** + * Called when a panel's menu item has been selected by the user. + * + * @param featureId The panel that the menu is in. + * @param item The menu item that was selected. + * + * @return boolean Return true to finish processing of selection, or + * false to perform the normal menu handling (calling its + * Runnable or sending a Message to its target Handler). + */ + public boolean onMenuItemSelected(int featureId, MenuItem item); + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java new file mode 100644 index 000000000..d7f110fc6 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserModel.java @@ -0,0 +1,1104 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.widget; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.database.DataSetObservable; +import android.os.Handler; +import android.text.TextUtils; +import android.util.Log; +import android.util.Xml; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +/** + *

+ * This class represents a data model for choosing a component for handing a + * given {@link Intent}. The model is responsible for querying the system for + * activities that can handle the given intent and order found activities + * based on historical data of previous choices. The historical data is stored + * in an application private file. If a client does not want to have persistent + * choice history the file can be omitted, thus the activities will be ordered + * based on historical usage for the current session. + *

+ *

+ * For each backing history file there is a singleton instance of this class. Thus, + * several clients that specify the same history file will share the same model. Note + * that if multiple clients are sharing the same model they should implement semantically + * equivalent functionality since setting the model intent will change the found + * activities and they may be inconsistent with the functionality of some of the clients. + * For example, choosing a share activity can be implemented by a single backing + * model and two different views for performing the selection. If however, one of the + * views is used for sharing but the other for importing, for example, then each + * view should be backed by a separate model. + *

+ *

+ * The way clients interact with this class is as follows: + *

+ *

+ *

+ * 
+ *  // Get a model and set it to a couple of clients with semantically similar function.
+ *  ActivityChooserModel dataModel =
+ *      ActivityChooserModel.get(context, "task_specific_history_file_name.xml");
+ *
+ *  ActivityChooserModelClient modelClient1 = getActivityChooserModelClient1();
+ *  modelClient1.setActivityChooserModel(dataModel);
+ *
+ *  ActivityChooserModelClient modelClient2 = getActivityChooserModelClient2();
+ *  modelClient2.setActivityChooserModel(dataModel);
+ *
+ *  // Set an intent to choose a an activity for.
+ *  dataModel.setIntent(intent);
+ * 
+ * 
+ * 

+ *

+ * Note: This class is thread safe. + *

+ * + * @hide + */ +class ActivityChooserModel extends DataSetObservable { + + /** + * Client that utilizes an {@link ActivityChooserModel}. + */ + public interface ActivityChooserModelClient { + + /** + * Sets the {@link ActivityChooserModel}. + * + * @param dataModel The model. + */ + public void setActivityChooserModel(ActivityChooserModel dataModel); + } + + /** + * Defines a sorter that is responsible for sorting the activities + * based on the provided historical choices and an intent. + */ + public interface ActivitySorter { + + /** + * Sorts the activities in descending order of relevance + * based on previous history and an intent. + * + * @param intent The {@link Intent}. + * @param activities Activities to be sorted. + * @param historicalRecords Historical records. + */ + // This cannot be done by a simple comparator since an Activity weight + // is computed from history. Note that Activity implements Comparable. + public void sort(Intent intent, List activities, + List historicalRecords); + } + + /** + * Listener for choosing an activity. + */ + public interface OnChooseActivityListener { + + /** + * Called when an activity has been chosen. The client can decide whether + * an activity can be chosen and if so the caller of + * {@link ActivityChooserModel#chooseActivity(int)} will receive and {@link Intent} + * for launching it. + *

+ * Note: Modifying the intent is not permitted and + * any changes to the latter will be ignored. + *

+ * + * @param host The listener's host model. + * @param intent The intent for launching the chosen activity. + * @return Whether the intent is handled and should not be delivered to clients. + * + * @see ActivityChooserModel#chooseActivity(int) + */ + public boolean onChooseActivity(ActivityChooserModel host, Intent intent); + } + + /** + * Flag for selecting debug mode. + */ + private static final boolean DEBUG = false; + + /** + * Tag used for logging. + */ + private static final String LOG_TAG = ActivityChooserModel.class.getSimpleName(); + + /** + * The root tag in the history file. + */ + private static final String TAG_HISTORICAL_RECORDS = "historical-records"; + + /** + * The tag for a record in the history file. + */ + private static final String TAG_HISTORICAL_RECORD = "historical-record"; + + /** + * Attribute for the activity. + */ + private static final String ATTRIBUTE_ACTIVITY = "activity"; + + /** + * Attribute for the choice time. + */ + private static final String ATTRIBUTE_TIME = "time"; + + /** + * Attribute for the choice weight. + */ + private static final String ATTRIBUTE_WEIGHT = "weight"; + + /** + * The default name of the choice history file. + */ + public static final String DEFAULT_HISTORY_FILE_NAME = + "activity_choser_model_history.xml"; + + /** + * The default maximal length of the choice history. + */ + public static final int DEFAULT_HISTORY_MAX_LENGTH = 50; + + /** + * The amount with which to inflate a chosen activity when set as default. + */ + private static final int DEFAULT_ACTIVITY_INFLATION = 5; + + /** + * Default weight for a choice record. + */ + private static final float DEFAULT_HISTORICAL_RECORD_WEIGHT = 1.0f; + + /** + * The extension of the history file. + */ + private static final String HISTORY_FILE_EXTENSION = ".xml"; + + /** + * An invalid item index. + */ + private static final int INVALID_INDEX = -1; + + /** + * Lock to guard the model registry. + */ + private static final Object sRegistryLock = new Object(); + + /** + * This the registry for data models. + */ + private static final Map sDataModelRegistry = + new HashMap(); + + /** + * Lock for synchronizing on this instance. + */ + private final Object mInstanceLock = new Object(); + + /** + * List of activities that can handle the current intent. + */ + private final List mActivites = new ArrayList(); + + /** + * List with historical choice records. + */ + private final List mHistoricalRecords = new ArrayList(); + + /** + * Context for accessing resources. + */ + private final Context mContext; + + /** + * The name of the history file that backs this model. + */ + private final String mHistoryFileName; + + /** + * The intent for which a activity is being chosen. + */ + private Intent mIntent; + + /** + * The sorter for ordering activities based on intent and past choices. + */ + private ActivitySorter mActivitySorter = new DefaultSorter(); + + /** + * The maximal length of the choice history. + */ + private int mHistoryMaxSize = DEFAULT_HISTORY_MAX_LENGTH; + + /** + * Flag whether choice history can be read. In general many clients can + * share the same data model and {@link #readHistoricalData()} may be called + * by arbitrary of them any number of times. Therefore, this class guarantees + * that the very first read succeeds and subsequent reads can be performed + * only after a call to {@link #persistHistoricalData()} followed by change + * of the share records. + */ + private boolean mCanReadHistoricalData = true; + + /** + * Flag whether the choice history was read. This is used to enforce that + * before calling {@link #persistHistoricalData()} a call to + * {@link #persistHistoricalData()} has been made. This aims to avoid a + * scenario in which a choice history file exits, it is not read yet and + * it is overwritten. Note that always all historical records are read in + * full and the file is rewritten. This is necessary since we need to + * purge old records that are outside of the sliding window of past choices. + */ + private boolean mReadShareHistoryCalled = false; + + /** + * Flag whether the choice records have changed. In general many clients can + * share the same data model and {@link #persistHistoricalData()} may be called + * by arbitrary of them any number of times. Therefore, this class guarantees + * that choice history will be persisted only if it has changed. + */ + private boolean mHistoricalRecordsChanged = true; + + /** + * Hander for scheduling work on client tread. + */ + private final Handler mHandler = new Handler(); + + /** + * Policy for controlling how the model handles chosen activities. + */ + private OnChooseActivityListener mActivityChoserModelPolicy; + + /** + * Gets the data model backed by the contents of the provided file with historical data. + * Note that only one data model is backed by a given file, thus multiple calls with + * the same file name will return the same model instance. If no such instance is present + * it is created. + *

+ * Note: To use the default historical data file clients should explicitly + * pass as file name {@link #DEFAULT_HISTORY_FILE_NAME}. If no persistence of the choice + * history is desired clients should pass null for the file name. In such + * case a new model is returned for each invocation. + *

+ * + *

+ * Always use difference historical data files for semantically different actions. + * For example, sharing is different from importing. + *

+ * + * @param context Context for loading resources. + * @param historyFileName File name with choice history, null + * if the model should not be backed by a file. In this case the activities + * will be ordered only by data from the current session. + * + * @return The model. + */ + public static ActivityChooserModel get(Context context, String historyFileName) { + synchronized (sRegistryLock) { + ActivityChooserModel dataModel = sDataModelRegistry.get(historyFileName); + if (dataModel == null) { + dataModel = new ActivityChooserModel(context, historyFileName); + sDataModelRegistry.put(historyFileName, dataModel); + } + dataModel.readHistoricalData(); + return dataModel; + } + } + + /** + * Creates a new instance. + * + * @param context Context for loading resources. + * @param historyFileName The history XML file. + */ + private ActivityChooserModel(Context context, String historyFileName) { + mContext = context.getApplicationContext(); + if (!TextUtils.isEmpty(historyFileName) + && !historyFileName.endsWith(HISTORY_FILE_EXTENSION)) { + mHistoryFileName = historyFileName + HISTORY_FILE_EXTENSION; + } else { + mHistoryFileName = historyFileName; + } + } + + /** + * Sets an intent for which to choose a activity. + *

+ * Note: Clients must set only semantically similar + * intents for each data model. + *

+ * + * @param intent The intent. + */ + public void setIntent(Intent intent) { + synchronized (mInstanceLock) { + if (mIntent == intent) { + return; + } + mIntent = intent; + loadActivitiesLocked(); + } + } + + /** + * Gets the intent for which a activity is being chosen. + * + * @return The intent. + */ + public Intent getIntent() { + synchronized (mInstanceLock) { + return mIntent; + } + } + + /** + * Gets the number of activities that can handle the intent. + * + * @return The activity count. + * + * @see #setIntent(Intent) + */ + public int getActivityCount() { + synchronized (mInstanceLock) { + return mActivites.size(); + } + } + + /** + * Gets an activity at a given index. + * + * @return The activity. + * + * @see ActivityResolveInfo + * @see #setIntent(Intent) + */ + public ResolveInfo getActivity(int index) { + synchronized (mInstanceLock) { + return mActivites.get(index).resolveInfo; + } + } + + /** + * Gets the index of a the given activity. + * + * @param activity The activity index. + * + * @return The index if found, -1 otherwise. + */ + public int getActivityIndex(ResolveInfo activity) { + List activities = mActivites; + final int activityCount = activities.size(); + for (int i = 0; i < activityCount; i++) { + ActivityResolveInfo currentActivity = activities.get(i); + if (currentActivity.resolveInfo == activity) { + return i; + } + } + return INVALID_INDEX; + } + + /** + * Chooses a activity to handle the current intent. This will result in + * adding a historical record for that action and construct intent with + * its component name set such that it can be immediately started by the + * client. + *

+ * Note: By calling this method the client guarantees + * that the returned intent will be started. This intent is returned to + * the client solely to let additional customization before the start. + *

+ * + * @return An {@link Intent} for launching the activity or null if the + * policy has consumed the intent. + * + * @see HistoricalRecord + * @see OnChooseActivityListener + */ + public Intent chooseActivity(int index) { + ActivityResolveInfo chosenActivity = mActivites.get(index); + + ComponentName chosenName = new ComponentName( + chosenActivity.resolveInfo.activityInfo.packageName, + chosenActivity.resolveInfo.activityInfo.name); + + Intent choiceIntent = new Intent(mIntent); + choiceIntent.setComponent(chosenName); + + if (mActivityChoserModelPolicy != null) { + // Do not allow the policy to change the intent. + Intent choiceIntentCopy = new Intent(choiceIntent); + final boolean handled = mActivityChoserModelPolicy.onChooseActivity(this, + choiceIntentCopy); + if (handled) { + return null; + } + } + + HistoricalRecord historicalRecord = new HistoricalRecord(chosenName, + System.currentTimeMillis(), DEFAULT_HISTORICAL_RECORD_WEIGHT); + addHisoricalRecord(historicalRecord); + + return choiceIntent; + } + + /** + * Sets the listener for choosing an activity. + * + * @param listener The listener. + */ + public void setOnChooseActivityListener(OnChooseActivityListener listener) { + mActivityChoserModelPolicy = listener; + } + + /** + * Gets the default activity, The default activity is defined as the one + * with highest rank i.e. the first one in the list of activities that can + * handle the intent. + * + * @return The default activity, null id not activities. + * + * @see #getActivity(int) + */ + public ResolveInfo getDefaultActivity() { + synchronized (mInstanceLock) { + if (!mActivites.isEmpty()) { + return mActivites.get(0).resolveInfo; + } + } + return null; + } + + /** + * Sets the default activity. The default activity is set by adding a + * historical record with weight high enough that this activity will + * become the highest ranked. Such a strategy guarantees that the default + * will eventually change if not used. Also the weight of the record for + * setting a default is inflated with a constant amount to guarantee that + * it will stay as default for awhile. + * + * @param index The index of the activity to set as default. + */ + public void setDefaultActivity(int index) { + ActivityResolveInfo newDefaultActivity = mActivites.get(index); + ActivityResolveInfo oldDefaultActivity = mActivites.get(0); + + final float weight; + if (oldDefaultActivity != null) { + // Add a record with weight enough to boost the chosen at the top. + weight = oldDefaultActivity.weight - newDefaultActivity.weight + + DEFAULT_ACTIVITY_INFLATION; + } else { + weight = DEFAULT_HISTORICAL_RECORD_WEIGHT; + } + + ComponentName defaultName = new ComponentName( + newDefaultActivity.resolveInfo.activityInfo.packageName, + newDefaultActivity.resolveInfo.activityInfo.name); + HistoricalRecord historicalRecord = new HistoricalRecord(defaultName, + System.currentTimeMillis(), weight); + addHisoricalRecord(historicalRecord); + } + + /** + * Reads the history data from the backing file if the latter + * was provided. Calling this method more than once before a call + * to {@link #persistHistoricalData()} has been made has no effect. + *

+ * Note: Historical data is read asynchronously and + * as soon as the reading is completed any registered + * {@link DataSetObserver}s will be notified. Also no historical + * data is read until this method is invoked. + *

+ */ + private void readHistoricalData() { + synchronized (mInstanceLock) { + if (!mCanReadHistoricalData || !mHistoricalRecordsChanged) { + return; + } + mCanReadHistoricalData = false; + mReadShareHistoryCalled = true; + if (!TextUtils.isEmpty(mHistoryFileName)) { + /*AsyncTask.*/SERIAL_EXECUTOR.execute(new HistoryLoader()); + } + } + } + + private static final Executor SERIAL_EXECUTOR = Executors.newSingleThreadExecutor(); + + /** + * Persists the history data to the backing file if the latter + * was provided. Calling this method before a call to {@link #readHistoricalData()} + * throws an exception. Calling this method more than one without choosing an + * activity has not effect. + * + * @throws IllegalStateException If this method is called before a call to + * {@link #readHistoricalData()}. + */ + private void persistHistoricalData() { + synchronized (mInstanceLock) { + if (!mReadShareHistoryCalled) { + throw new IllegalStateException("No preceding call to #readHistoricalData"); + } + if (!mHistoricalRecordsChanged) { + return; + } + mHistoricalRecordsChanged = false; + mCanReadHistoricalData = true; + if (!TextUtils.isEmpty(mHistoryFileName)) { + /*AsyncTask.*/SERIAL_EXECUTOR.execute(new HistoryPersister()); + } + } + } + + /** + * Sets the sorter for ordering activities based on historical data and an intent. + * + * @param activitySorter The sorter. + * + * @see ActivitySorter + */ + public void setActivitySorter(ActivitySorter activitySorter) { + synchronized (mInstanceLock) { + if (mActivitySorter == activitySorter) { + return; + } + mActivitySorter = activitySorter; + sortActivities(); + } + } + + /** + * Sorts the activities based on history and an intent. If + * a sorter is not specified this a default implementation is used. + * + * @see #setActivitySorter(ActivitySorter) + */ + private void sortActivities() { + synchronized (mInstanceLock) { + if (mActivitySorter != null && !mActivites.isEmpty()) { + mActivitySorter.sort(mIntent, mActivites, + Collections.unmodifiableList(mHistoricalRecords)); + notifyChanged(); + } + } + } + + /** + * Sets the maximal size of the historical data. Defaults to + * {@link #DEFAULT_HISTORY_MAX_LENGTH} + *

+ * Note: Setting this property will immediately + * enforce the specified max history size by dropping enough old + * historical records to enforce the desired size. Thus, any + * records that exceed the history size will be discarded and + * irreversibly lost. + *

+ * + * @param historyMaxSize The max history size. + */ + public void setHistoryMaxSize(int historyMaxSize) { + synchronized (mInstanceLock) { + if (mHistoryMaxSize == historyMaxSize) { + return; + } + mHistoryMaxSize = historyMaxSize; + pruneExcessiveHistoricalRecordsLocked(); + sortActivities(); + } + } + + /** + * Gets the history max size. + * + * @return The history max size. + */ + public int getHistoryMaxSize() { + synchronized (mInstanceLock) { + return mHistoryMaxSize; + } + } + + /** + * Gets the history size. + * + * @return The history size. + */ + public int getHistorySize() { + synchronized (mInstanceLock) { + return mHistoricalRecords.size(); + } + } + + /** + * Adds a historical record. + * + * @param historicalRecord The record to add. + * @return True if the record was added. + */ + private boolean addHisoricalRecord(HistoricalRecord historicalRecord) { + synchronized (mInstanceLock) { + final boolean added = mHistoricalRecords.add(historicalRecord); + if (added) { + mHistoricalRecordsChanged = true; + pruneExcessiveHistoricalRecordsLocked(); + persistHistoricalData(); + sortActivities(); + } + return added; + } + } + + /** + * Prunes older excessive records to guarantee {@link #mHistoryMaxSize}. + */ + private void pruneExcessiveHistoricalRecordsLocked() { + List choiceRecords = mHistoricalRecords; + final int pruneCount = choiceRecords.size() - mHistoryMaxSize; + if (pruneCount <= 0) { + return; + } + mHistoricalRecordsChanged = true; + for (int i = 0; i < pruneCount; i++) { + HistoricalRecord prunedRecord = choiceRecords.remove(0); + if (DEBUG) { + Log.i(LOG_TAG, "Pruned: " + prunedRecord); + } + } + } + + /** + * Loads the activities. + */ + private void loadActivitiesLocked() { + mActivites.clear(); + if (mIntent != null) { + List resolveInfos = + mContext.getPackageManager().queryIntentActivities(mIntent, 0); + final int resolveInfoCount = resolveInfos.size(); + for (int i = 0; i < resolveInfoCount; i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + mActivites.add(new ActivityResolveInfo(resolveInfo)); + } + sortActivities(); + } else { + notifyChanged(); + } + } + + /** + * Represents a record in the history. + */ + public final static class HistoricalRecord { + + /** + * The activity name. + */ + public final ComponentName activity; + + /** + * The choice time. + */ + public final long time; + + /** + * The record weight. + */ + public final float weight; + + /** + * Creates a new instance. + * + * @param activityName The activity component name flattened to string. + * @param time The time the activity was chosen. + * @param weight The weight of the record. + */ + public HistoricalRecord(String activityName, long time, float weight) { + this(ComponentName.unflattenFromString(activityName), time, weight); + } + + /** + * Creates a new instance. + * + * @param activityName The activity name. + * @param time The time the activity was chosen. + * @param weight The weight of the record. + */ + public HistoricalRecord(ComponentName activityName, long time, float weight) { + this.activity = activityName; + this.time = time; + this.weight = weight; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((activity == null) ? 0 : activity.hashCode()); + result = prime * result + (int) (time ^ (time >>> 32)); + result = prime * result + Float.floatToIntBits(weight); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + HistoricalRecord other = (HistoricalRecord) obj; + if (activity == null) { + if (other.activity != null) { + return false; + } + } else if (!activity.equals(other.activity)) { + return false; + } + if (time != other.time) { + return false; + } + if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("["); + builder.append("; activity:").append(activity); + builder.append("; time:").append(time); + builder.append("; weight:").append(new BigDecimal(weight)); + builder.append("]"); + return builder.toString(); + } + } + + /** + * Represents an activity. + */ + public final class ActivityResolveInfo implements Comparable { + + /** + * The {@link ResolveInfo} of the activity. + */ + public final ResolveInfo resolveInfo; + + /** + * Weight of the activity. Useful for sorting. + */ + public float weight; + + /** + * Creates a new instance. + * + * @param resolveInfo activity {@link ResolveInfo}. + */ + public ActivityResolveInfo(ResolveInfo resolveInfo) { + this.resolveInfo = resolveInfo; + } + + @Override + public int hashCode() { + return 31 + Float.floatToIntBits(weight); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ActivityResolveInfo other = (ActivityResolveInfo) obj; + if (Float.floatToIntBits(weight) != Float.floatToIntBits(other.weight)) { + return false; + } + return true; + } + + public int compareTo(ActivityResolveInfo another) { + return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("["); + builder.append("resolveInfo:").append(resolveInfo.toString()); + builder.append("; weight:").append(new BigDecimal(weight)); + builder.append("]"); + return builder.toString(); + } + } + + /** + * Default activity sorter implementation. + */ + private final class DefaultSorter implements ActivitySorter { + private static final float WEIGHT_DECAY_COEFFICIENT = 0.95f; + + private final Map mPackageNameToActivityMap = + new HashMap(); + + public void sort(Intent intent, List activities, + List historicalRecords) { + Map packageNameToActivityMap = + mPackageNameToActivityMap; + packageNameToActivityMap.clear(); + + final int activityCount = activities.size(); + for (int i = 0; i < activityCount; i++) { + ActivityResolveInfo activity = activities.get(i); + activity.weight = 0.0f; + String packageName = activity.resolveInfo.activityInfo.packageName; + packageNameToActivityMap.put(packageName, activity); + } + + final int lastShareIndex = historicalRecords.size() - 1; + float nextRecordWeight = 1; + for (int i = lastShareIndex; i >= 0; i--) { + HistoricalRecord historicalRecord = historicalRecords.get(i); + String packageName = historicalRecord.activity.getPackageName(); + ActivityResolveInfo activity = packageNameToActivityMap.get(packageName); + if (activity != null) { + activity.weight += historicalRecord.weight * nextRecordWeight; + nextRecordWeight = nextRecordWeight * WEIGHT_DECAY_COEFFICIENT; + } + } + + Collections.sort(activities); + + if (DEBUG) { + for (int i = 0; i < activityCount; i++) { + Log.i(LOG_TAG, "Sorted: " + activities.get(i)); + } + } + } + } + + /** + * Command for reading the historical records from a file off the UI thread. + */ + private final class HistoryLoader implements Runnable { + + public void run() { + FileInputStream fis = null; + try { + fis = mContext.openFileInput(mHistoryFileName); + } catch (FileNotFoundException fnfe) { + if (DEBUG) { + Log.i(LOG_TAG, "Could not open historical records file: " + mHistoryFileName); + } + return; + } + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(fis, null); + + int type = XmlPullParser.START_DOCUMENT; + while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) { + type = parser.next(); + } + + if (!TAG_HISTORICAL_RECORDS.equals(parser.getName())) { + throw new XmlPullParserException("Share records file does not start with " + + TAG_HISTORICAL_RECORDS + " tag."); + } + + List readRecords = new ArrayList(); + + while (true) { + type = parser.next(); + if (type == XmlPullParser.END_DOCUMENT) { + break; + } + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + String nodeName = parser.getName(); + if (!TAG_HISTORICAL_RECORD.equals(nodeName)) { + throw new XmlPullParserException("Share records file not well-formed."); + } + + String activity = parser.getAttributeValue(null, ATTRIBUTE_ACTIVITY); + final long time = + Long.parseLong(parser.getAttributeValue(null, ATTRIBUTE_TIME)); + final float weight = + Float.parseFloat(parser.getAttributeValue(null, ATTRIBUTE_WEIGHT)); + + HistoricalRecord readRecord = new HistoricalRecord(activity, time, + weight); + readRecords.add(readRecord); + + if (DEBUG) { + Log.i(LOG_TAG, "Read " + readRecord.toString()); + } + } + + if (DEBUG) { + Log.i(LOG_TAG, "Read " + readRecords.size() + " historical records."); + } + + synchronized (mInstanceLock) { + Set uniqueShareRecords = + new LinkedHashSet(readRecords); + + // Make sure no duplicates. Example: Read a file with + // one record, add one record, persist the two records, + // add a record, read the persisted records - the + // read two records should not be added again. + List historicalRecords = mHistoricalRecords; + final int historicalRecordsCount = historicalRecords.size(); + for (int i = historicalRecordsCount - 1; i >= 0; i--) { + HistoricalRecord historicalRecord = historicalRecords.get(i); + uniqueShareRecords.add(historicalRecord); + } + + if (historicalRecords.size() == uniqueShareRecords.size()) { + return; + } + + // Make sure the oldest records go to the end. + historicalRecords.clear(); + historicalRecords.addAll(uniqueShareRecords); + + mHistoricalRecordsChanged = true; + + // Do this on the client thread since the client may be on the UI + // thread, wait for data changes which happen during sorting, and + // perform UI modification based on the data change. + mHandler.post(new Runnable() { + public void run() { + pruneExcessiveHistoricalRecordsLocked(); + sortActivities(); + } + }); + } + } catch (XmlPullParserException xppe) { + Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, xppe); + } catch (IOException ioe) { + Log.e(LOG_TAG, "Error reading historical recrod file: " + mHistoryFileName, ioe); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ioe) { + /* ignore */ + } + } + } + } + } + + /** + * Command for persisting the historical records to a file off the UI thread. + */ + private final class HistoryPersister implements Runnable { + + public void run() { + FileOutputStream fos = null; + List records = null; + + synchronized (mInstanceLock) { + records = new ArrayList(mHistoricalRecords); + } + + try { + fos = mContext.openFileOutput(mHistoryFileName, Context.MODE_PRIVATE); + } catch (FileNotFoundException fnfe) { + Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, fnfe); + return; + } + + XmlSerializer serializer = Xml.newSerializer(); + + try { + serializer.setOutput(fos, null); + serializer.startDocument("UTF-8", true); + serializer.startTag(null, TAG_HISTORICAL_RECORDS); + + final int recordCount = records.size(); + for (int i = 0; i < recordCount; i++) { + HistoricalRecord record = records.remove(0); + serializer.startTag(null, TAG_HISTORICAL_RECORD); + serializer.attribute(null, ATTRIBUTE_ACTIVITY, record.activity.flattenToString()); + serializer.attribute(null, ATTRIBUTE_TIME, String.valueOf(record.time)); + serializer.attribute(null, ATTRIBUTE_WEIGHT, String.valueOf(record.weight)); + serializer.endTag(null, TAG_HISTORICAL_RECORD); + if (DEBUG) { + Log.i(LOG_TAG, "Wrote " + record.toString()); + } + } + + serializer.endTag(null, TAG_HISTORICAL_RECORDS); + serializer.endDocument(); + + if (DEBUG) { + Log.i(LOG_TAG, "Wrote " + recordCount + " historical records."); + } + } catch (IllegalArgumentException iae) { + Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, iae); + } catch (IllegalStateException ise) { + Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ise); + } catch (IOException ioe) { + Log.e(LOG_TAG, "Error writing historical recrod file: " + mHistoryFileName, ioe); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + /* ignore */ + } + } + } + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java new file mode 100644 index 000000000..e19ea9e9e --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ActivityChooserView.java @@ -0,0 +1,827 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.widget; + +import android.os.Build; +import com.actionbarsherlock.R; +import com.actionbarsherlock.internal.widget.IcsLinearLayout; +import com.actionbarsherlock.internal.widget.IcsListPopupWindow; +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.widget.ActivityChooserModel.ActivityChooserModelClient; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.TextView; + +/** + * This class is a view for choosing an activity for handling a given {@link Intent}. + *

+ * The view is composed of two adjacent buttons: + *

    + *
  • + * The left button is an immediate action and allows one click activity choosing. + * Tapping this button immediately executes the intent without requiring any further + * user input. Long press on this button shows a popup for changing the default + * activity. + *
  • + *
  • + * The right button is an overflow action and provides an optimized menu + * of additional activities. Tapping this button shows a popup anchored to this + * view, listing the most frequently used activities. This list is initially + * limited to a small number of items in frequency used order. The last item, + * "Show all..." serves as an affordance to display all available activities. + *
  • + *
+ *

+ * + * @hide + */ +class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient { + + /** + * An adapter for displaying the activities in an {@link AdapterView}. + */ + private final ActivityChooserViewAdapter mAdapter; + + /** + * Implementation of various interfaces to avoid publishing them in the APIs. + */ + private final Callbacks mCallbacks; + + /** + * The content of this view. + */ + private final IcsLinearLayout mActivityChooserContent; + + /** + * Stores the background drawable to allow hiding and latter showing. + */ + private final Drawable mActivityChooserContentBackground; + + /** + * The expand activities action button; + */ + private final FrameLayout mExpandActivityOverflowButton; + + /** + * The image for the expand activities action button; + */ + private final ImageView mExpandActivityOverflowButtonImage; + + /** + * The default activities action button; + */ + private final FrameLayout mDefaultActivityButton; + + /** + * The image for the default activities action button; + */ + private final ImageView mDefaultActivityButtonImage; + + /** + * The maximal width of the list popup. + */ + private final int mListPopupMaxWidth; + + /** + * The ActionProvider hosting this view, if applicable. + */ + ActionProvider mProvider; + + /** + * Observer for the model data. + */ + private final DataSetObserver mModelDataSetOberver = new DataSetObserver() { + + @Override + public void onChanged() { + super.onChanged(); + mAdapter.notifyDataSetChanged(); + } + @Override + public void onInvalidated() { + super.onInvalidated(); + mAdapter.notifyDataSetInvalidated(); + } + }; + + private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (isShowingPopup()) { + if (!isShown()) { + getListPopupWindow().dismiss(); + } else { + getListPopupWindow().show(); + if (mProvider != null) { + mProvider.subUiVisibilityChanged(true); + } + } + } + } + }; + + /** + * Popup window for showing the activity overflow list. + */ + private IcsListPopupWindow mListPopupWindow; + + /** + * Listener for the dismissal of the popup/alert. + */ + private PopupWindow.OnDismissListener mOnDismissListener; + + /** + * Flag whether a default activity currently being selected. + */ + private boolean mIsSelectingDefaultActivity; + + /** + * The count of activities in the popup. + */ + private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT; + + /** + * Flag whether this view is attached to a window. + */ + private boolean mIsAttachedToWindow; + + /** + * String resource for formatting content description of the default target. + */ + private int mDefaultActionButtonContentDescription; + + private final Context mContext; + + /** + * Create a new instance. + * + * @param context The application environment. + */ + public ActivityChooserView(Context context) { + this(context, null); + } + + /** + * Create a new instance. + * + * @param context The application environment. + * @param attrs A collection of attributes. + */ + public ActivityChooserView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /** + * Create a new instance. + * + * @param context The application environment. + * @param attrs A collection of attributes. + * @param defStyle The default style to apply to this view. + */ + public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mContext = context; + + TypedArray attributesArray = context.obtainStyledAttributes(attrs, + R.styleable.SherlockActivityChooserView, defStyle, 0); + + mInitialActivityCount = attributesArray.getInt( + R.styleable.SherlockActivityChooserView_initialActivityCount, + ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT); + + Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable( + R.styleable.SherlockActivityChooserView_expandActivityOverflowButtonDrawable); + + attributesArray.recycle(); + + LayoutInflater inflater = LayoutInflater.from(mContext); + inflater.inflate(R.layout.abs__activity_chooser_view, this, true); + + mCallbacks = new Callbacks(); + + mActivityChooserContent = (IcsLinearLayout) findViewById(R.id.abs__activity_chooser_view_content); + mActivityChooserContentBackground = mActivityChooserContent.getBackground(); + + mDefaultActivityButton = (FrameLayout) findViewById(R.id.abs__default_activity_button); + mDefaultActivityButton.setOnClickListener(mCallbacks); + mDefaultActivityButton.setOnLongClickListener(mCallbacks); + mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.abs__image); + + mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.abs__expand_activities_button); + mExpandActivityOverflowButton.setOnClickListener(mCallbacks); + mExpandActivityOverflowButtonImage = + (ImageView) mExpandActivityOverflowButton.findViewById(R.id.abs__image); + mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable); + + mAdapter = new ActivityChooserViewAdapter(); + mAdapter.registerDataSetObserver(new DataSetObserver() { + @Override + public void onChanged() { + super.onChanged(); + updateAppearance(); + } + }); + + Resources resources = context.getResources(); + mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2, + resources.getDimensionPixelSize(R.dimen.abs__config_prefDialogWidth)); + } + + /** + * {@inheritDoc} + */ + public void setActivityChooserModel(ActivityChooserModel dataModel) { + mAdapter.setDataModel(dataModel); + if (isShowingPopup()) { + dismissPopup(); + showPopup(); + } + } + + /** + * Sets the background for the button that expands the activity + * overflow list. + * + * Note: Clients would like to set this drawable + * as a clue about the action the chosen activity will perform. For + * example, if a share activity is to be chosen the drawable should + * give a clue that sharing is to be performed. + * + * @param drawable The drawable. + */ + public void setExpandActivityOverflowButtonDrawable(Drawable drawable) { + mExpandActivityOverflowButtonImage.setImageDrawable(drawable); + } + + /** + * Sets the content description for the button that expands the activity + * overflow list. + * + * description as a clue about the action performed by the button. + * For example, if a share activity is to be chosen the content + * description should be something like "Share with". + * + * @param resourceId The content description resource id. + */ + public void setExpandActivityOverflowButtonContentDescription(int resourceId) { + CharSequence contentDescription = mContext.getString(resourceId); + mExpandActivityOverflowButtonImage.setContentDescription(contentDescription); + } + + /** + * Set the provider hosting this view, if applicable. + * @hide Internal use only + */ + public void setProvider(ActionProvider provider) { + mProvider = provider; + } + + /** + * Shows the popup window with activities. + * + * @return True if the popup was shown, false if already showing. + */ + public boolean showPopup() { + if (isShowingPopup() || !mIsAttachedToWindow) { + return false; + } + mIsSelectingDefaultActivity = false; + showPopupUnchecked(mInitialActivityCount); + return true; + } + + /** + * Shows the popup no matter if it was already showing. + * + * @param maxActivityCount The max number of activities to display. + */ + private void showPopupUnchecked(int maxActivityCount) { + if (mAdapter.getDataModel() == null) { + throw new IllegalStateException("No data model. Did you call #setDataModel?"); + } + + getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener); + + final boolean defaultActivityButtonShown = + mDefaultActivityButton.getVisibility() == VISIBLE; + + final int activityCount = mAdapter.getActivityCount(); + final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0; + if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED + && activityCount > maxActivityCount + maxActivityCountOffset) { + mAdapter.setShowFooterView(true); + mAdapter.setMaxActivityCount(maxActivityCount - 1); + } else { + mAdapter.setShowFooterView(false); + mAdapter.setMaxActivityCount(maxActivityCount); + } + + IcsListPopupWindow popupWindow = getListPopupWindow(); + if (!popupWindow.isShowing()) { + if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) { + mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown); + } else { + mAdapter.setShowDefaultActivity(false, false); + } + final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth); + popupWindow.setContentWidth(contentWidth); + popupWindow.show(); + if (mProvider != null) { + mProvider.subUiVisibilityChanged(true); + } + popupWindow.getListView().setContentDescription(mContext.getString( + R.string.abs__activitychooserview_choose_application)); + } + } + + /** + * Dismisses the popup window with activities. + * + * @return True if dismissed, false if already dismissed. + */ + public boolean dismissPopup() { + if (isShowingPopup()) { + getListPopupWindow().dismiss(); + ViewTreeObserver viewTreeObserver = getViewTreeObserver(); + if (viewTreeObserver.isAlive()) { + viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); + } + } + return true; + } + + /** + * Gets whether the popup window with activities is shown. + * + * @return True if the popup is shown. + */ + public boolean isShowingPopup() { + return getListPopupWindow().isShowing(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + ActivityChooserModel dataModel = mAdapter.getDataModel(); + if (dataModel != null) { + dataModel.registerObserver(mModelDataSetOberver); + } + mIsAttachedToWindow = true; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + ActivityChooserModel dataModel = mAdapter.getDataModel(); + if (dataModel != null) { + try { + dataModel.unregisterObserver(mModelDataSetOberver); + } catch (IllegalStateException e) { + //Oh, well... fixes issue #557 + } + } + ViewTreeObserver viewTreeObserver = getViewTreeObserver(); + if (viewTreeObserver.isAlive()) { + viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener); + } + mIsAttachedToWindow = false; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + View child = mActivityChooserContent; + // If the default action is not visible we want to be as tall as the + // ActionBar so if this widget is used in the latter it will look as + // a normal action button. + if (mDefaultActivityButton.getVisibility() != VISIBLE) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), + MeasureSpec.EXACTLY); + } + measureChild(child, widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight()); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + mActivityChooserContent.layout(0, 0, right - left, bottom - top); + if (getListPopupWindow().isShowing()) { + showPopupUnchecked(mAdapter.getMaxActivityCount()); + } else { + dismissPopup(); + } + } + + public ActivityChooserModel getDataModel() { + return mAdapter.getDataModel(); + } + + /** + * Sets a listener to receive a callback when the popup is dismissed. + * + * @param listener The listener to be notified. + */ + public void setOnDismissListener(PopupWindow.OnDismissListener listener) { + mOnDismissListener = listener; + } + + /** + * Sets the initial count of items shown in the activities popup + * i.e. the items before the popup is expanded. This is an upper + * bound since it is not guaranteed that such number of intent + * handlers exist. + * + * @param itemCount The initial popup item count. + */ + public void setInitialActivityCount(int itemCount) { + mInitialActivityCount = itemCount; + } + + /** + * Sets a content description of the default action button. This + * resource should be a string taking one formatting argument and + * will be used for formatting the content description of the button + * dynamically as the default target changes. For example, a resource + * pointing to the string "share with %1$s" will result in a content + * description "share with Bluetooth" for the Bluetooth activity. + * + * @param resourceId The resource id. + */ + public void setDefaultActionButtonContentDescription(int resourceId) { + mDefaultActionButtonContentDescription = resourceId; + } + + /** + * Gets the list popup window which is lazily initialized. + * + * @return The popup. + */ + private IcsListPopupWindow getListPopupWindow() { + if (mListPopupWindow == null) { + mListPopupWindow = new IcsListPopupWindow(getContext()); + mListPopupWindow.setAdapter(mAdapter); + mListPopupWindow.setAnchorView(ActivityChooserView.this); + mListPopupWindow.setModal(true); + mListPopupWindow.setOnItemClickListener(mCallbacks); + mListPopupWindow.setOnDismissListener(mCallbacks); + } + return mListPopupWindow; + } + + /** + * Updates the buttons state. + */ + private void updateAppearance() { + // Expand overflow button. + if (mAdapter.getCount() > 0) { + mExpandActivityOverflowButton.setEnabled(true); + } else { + mExpandActivityOverflowButton.setEnabled(false); + } + // Default activity button. + final int activityCount = mAdapter.getActivityCount(); + final int historySize = mAdapter.getHistorySize(); + if (activityCount > 0 && historySize > 0) { + mDefaultActivityButton.setVisibility(VISIBLE); + ResolveInfo activity = mAdapter.getDefaultActivity(); + PackageManager packageManager = mContext.getPackageManager(); + mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager)); + if (mDefaultActionButtonContentDescription != 0) { + CharSequence label = activity.loadLabel(packageManager); + String contentDescription = mContext.getString( + mDefaultActionButtonContentDescription, label); + mDefaultActivityButton.setContentDescription(contentDescription); + } + } else { + mDefaultActivityButton.setVisibility(View.GONE); + } + // Activity chooser content. + if (mDefaultActivityButton.getVisibility() == VISIBLE) { + mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground); + } else { + mActivityChooserContent.setBackgroundDrawable(null); + mActivityChooserContent.setPadding(0, 0, 0, 0); + } + } + + /** + * Interface implementation to avoid publishing them in the APIs. + */ + private class Callbacks implements AdapterView.OnItemClickListener, + View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener { + + // AdapterView#OnItemClickListener + public void onItemClick(AdapterView parent, View view, int position, long id) { + ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter(); + final int itemViewType = adapter.getItemViewType(position); + switch (itemViewType) { + case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: { + showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED); + } break; + case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: { + dismissPopup(); + if (mIsSelectingDefaultActivity) { + // The item at position zero is the default already. + if (position > 0) { + mAdapter.getDataModel().setDefaultActivity(position); + } + } else { + // If the default target is not shown in the list, the first + // item in the model is default action => adjust index + position = mAdapter.getShowDefaultActivity() ? position : position + 1; + Intent launchIntent = mAdapter.getDataModel().chooseActivity(position); + if (launchIntent != null) { + mContext.startActivity(launchIntent); + } + } + } break; + default: + throw new IllegalArgumentException(); + } + } + + // View.OnClickListener + public void onClick(View view) { + if (view == mDefaultActivityButton) { + dismissPopup(); + ResolveInfo defaultActivity = mAdapter.getDefaultActivity(); + final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity); + Intent launchIntent = mAdapter.getDataModel().chooseActivity(index); + if (launchIntent != null) { + mContext.startActivity(launchIntent); + } + } else if (view == mExpandActivityOverflowButton) { + mIsSelectingDefaultActivity = false; + showPopupUnchecked(mInitialActivityCount); + } else { + throw new IllegalArgumentException(); + } + } + + // OnLongClickListener#onLongClick + @Override + public boolean onLongClick(View view) { + if (view == mDefaultActivityButton) { + if (mAdapter.getCount() > 0) { + mIsSelectingDefaultActivity = true; + showPopupUnchecked(mInitialActivityCount); + } + } else { + throw new IllegalArgumentException(); + } + return true; + } + + // PopUpWindow.OnDismissListener#onDismiss + public void onDismiss() { + notifyOnDismissListener(); + if (mProvider != null) { + mProvider.subUiVisibilityChanged(false); + } + } + + private void notifyOnDismissListener() { + if (mOnDismissListener != null) { + mOnDismissListener.onDismiss(); + } + } + } + + private static class SetActivated { + public static void invoke(View view, boolean activated) { + view.setActivated(activated); + } + } + + private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; + + /** + * Adapter for backing the list of activities shown in the popup. + */ + private class ActivityChooserViewAdapter extends BaseAdapter { + + public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE; + + public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4; + + private static final int ITEM_VIEW_TYPE_ACTIVITY = 0; + + private static final int ITEM_VIEW_TYPE_FOOTER = 1; + + private static final int ITEM_VIEW_TYPE_COUNT = 3; + + private ActivityChooserModel mDataModel; + + private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT; + + private boolean mShowDefaultActivity; + + private boolean mHighlightDefaultActivity; + + private boolean mShowFooterView; + + public void setDataModel(ActivityChooserModel dataModel) { + ActivityChooserModel oldDataModel = mAdapter.getDataModel(); + if (oldDataModel != null && isShown()) { + try { + oldDataModel.unregisterObserver(mModelDataSetOberver); + } catch (IllegalStateException e) { + //Oh, well... fixes issue #557 + } + } + mDataModel = dataModel; + if (dataModel != null && isShown()) { + dataModel.registerObserver(mModelDataSetOberver); + } + notifyDataSetChanged(); + } + + @Override + public int getItemViewType(int position) { + if (mShowFooterView && position == getCount() - 1) { + return ITEM_VIEW_TYPE_FOOTER; + } else { + return ITEM_VIEW_TYPE_ACTIVITY; + } + } + + @Override + public int getViewTypeCount() { + return ITEM_VIEW_TYPE_COUNT; + } + + public int getCount() { + int count = 0; + int activityCount = mDataModel.getActivityCount(); + if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { + activityCount--; + } + count = Math.min(activityCount, mMaxActivityCount); + if (mShowFooterView) { + count++; + } + return count; + } + + public Object getItem(int position) { + final int itemViewType = getItemViewType(position); + switch (itemViewType) { + case ITEM_VIEW_TYPE_FOOTER: + return null; + case ITEM_VIEW_TYPE_ACTIVITY: + if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) { + position++; + } + return mDataModel.getActivity(position); + default: + throw new IllegalArgumentException(); + } + } + + public long getItemId(int position) { + return position; + } + + public View getView(int position, View convertView, ViewGroup parent) { + final int itemViewType = getItemViewType(position); + switch (itemViewType) { + case ITEM_VIEW_TYPE_FOOTER: + if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) { + convertView = LayoutInflater.from(getContext()).inflate( + R.layout.abs__activity_chooser_view_list_item, parent, false); + convertView.setId(ITEM_VIEW_TYPE_FOOTER); + TextView titleView = (TextView) convertView.findViewById(R.id.abs__title); + titleView.setText(mContext.getString( + R.string.abs__activity_chooser_view_see_all)); + } + return convertView; + case ITEM_VIEW_TYPE_ACTIVITY: + if (convertView == null || convertView.getId() != R.id.abs__list_item) { + convertView = LayoutInflater.from(getContext()).inflate( + R.layout.abs__activity_chooser_view_list_item, parent, false); + } + PackageManager packageManager = mContext.getPackageManager(); + // Set the icon + ImageView iconView = (ImageView) convertView.findViewById(R.id.abs__icon); + ResolveInfo activity = (ResolveInfo) getItem(position); + iconView.setImageDrawable(activity.loadIcon(packageManager)); + // Set the title. + TextView titleView = (TextView) convertView.findViewById(R.id.abs__title); + titleView.setText(activity.loadLabel(packageManager)); + if (IS_HONEYCOMB) { + // Highlight the default. + if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) { + SetActivated.invoke(convertView, true); + } else { + SetActivated.invoke(convertView, false); + } + } + return convertView; + default: + throw new IllegalArgumentException(); + } + } + + public int measureContentWidth() { + // The user may have specified some of the target not to be shown but we + // want to measure all of them since after expansion they should fit. + final int oldMaxActivityCount = mMaxActivityCount; + mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED; + + int contentWidth = 0; + View itemView = null; + + final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); + final int count = getCount(); + + for (int i = 0; i < count; i++) { + itemView = getView(i, itemView, null); + itemView.measure(widthMeasureSpec, heightMeasureSpec); + contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth()); + } + + mMaxActivityCount = oldMaxActivityCount; + + return contentWidth; + } + + public void setMaxActivityCount(int maxActivityCount) { + if (mMaxActivityCount != maxActivityCount) { + mMaxActivityCount = maxActivityCount; + notifyDataSetChanged(); + } + } + + public ResolveInfo getDefaultActivity() { + return mDataModel.getDefaultActivity(); + } + + public void setShowFooterView(boolean showFooterView) { + if (mShowFooterView != showFooterView) { + mShowFooterView = showFooterView; + notifyDataSetChanged(); + } + } + + public int getActivityCount() { + return mDataModel.getActivityCount(); + } + + public int getHistorySize() { + return mDataModel.getHistorySize(); + } + + public int getMaxActivityCount() { + return mMaxActivityCount; + } + + public ActivityChooserModel getDataModel() { + return mDataModel; + } + + public void setShowDefaultActivity(boolean showDefaultActivity, + boolean highlightDefaultActivity) { + if (mShowDefaultActivity != showDefaultActivity + || mHighlightDefaultActivity != highlightDefaultActivity) { + mShowDefaultActivity = showDefaultActivity; + mHighlightDefaultActivity = highlightDefaultActivity; + notifyDataSetChanged(); + } + } + + public boolean getShowDefaultActivity() { + return mShowDefaultActivity; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java new file mode 100644 index 000000000..c9e7897d4 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SearchView.java @@ -0,0 +1,1811 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.widget; + +import android.app.PendingIntent; +import android.app.SearchManager; +import android.app.SearchableInfo; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.database.Cursor; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.ResultReceiver; +import android.speech.RecognizerIntent; +import android.support.v4.view.KeyEventCompat; +import android.support.v4.widget.CursorAdapter; +import android.text.Editable; +import android.text.InputType; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.text.style.ImageSpan; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.AutoCompleteTextView; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import com.actionbarsherlock.R; +import com.actionbarsherlock.view.CollapsibleActionView; + +import java.lang.reflect.Method; +import java.util.WeakHashMap; + +import static com.actionbarsherlock.widget.SuggestionsAdapter.getColumnString; + +/** + * A widget that provides a user interface for the user to enter a search query and submit a request + * to a search provider. Shows a list of query suggestions or results, if available, and allows the + * user to pick a suggestion or result to launch into. + * + *

+ * When the SearchView is used in an ActionBar as an action view for a collapsible menu item, it + * needs to be set to iconified by default using {@link #setIconifiedByDefault(boolean) + * setIconifiedByDefault(true)}. This is the default, so nothing needs to be done. + *

+ *

+ * If you want the search field to always be visible, then call setIconifiedByDefault(false). + *

+ * + *
+ *

Developer Guides

+ *

For information about using {@code SearchView}, read the + * Search developer guide.

+ *
+ * + * @see android.view.MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + * @attr ref android.R.styleable#SearchView_imeOptions + * @attr ref android.R.styleable#SearchView_inputType + * @attr ref android.R.styleable#SearchView_maxWidth + * @attr ref android.R.styleable#SearchView_queryHint + */ +public class SearchView extends LinearLayout implements CollapsibleActionView { + + private static final boolean DBG = false; + private static final String LOG_TAG = "SearchView"; + + /** + * Private constant for removing the microphone in the keyboard. + */ + private static final String IME_OPTION_NO_MICROPHONE = "nm"; + + private OnQueryTextListener mOnQueryChangeListener; + private OnCloseListener mOnCloseListener; + private OnFocusChangeListener mOnQueryTextFocusChangeListener; + private OnSuggestionListener mOnSuggestionListener; + private OnClickListener mOnSearchClickListener; + + private boolean mIconifiedByDefault; + private boolean mIconified; + private CursorAdapter mSuggestionsAdapter; + private View mSearchButton; + private View mSubmitButton; + private View mSearchPlate; + private View mSubmitArea; + private ImageView mCloseButton; + private View mSearchEditFrame; + private View mVoiceButton; + private SearchAutoComplete mQueryTextView; + private View mDropDownAnchor; + private ImageView mSearchHintIcon; + private boolean mSubmitButtonEnabled; + private CharSequence mQueryHint; + private boolean mQueryRefinement; + private boolean mClearingFocus; + private int mMaxWidth; + private boolean mVoiceButtonEnabled; + private CharSequence mOldQueryText; + private CharSequence mUserQuery; + private boolean mExpandedInActionView; + private int mCollapsedImeOptions; + + private SearchableInfo mSearchable; + private Bundle mAppSearchData; + + /* + * SearchView can be set expanded before the IME is ready to be shown during + * initial UI setup. The show operation is asynchronous to account for this. + */ + private Runnable mShowImeRunnable = new Runnable() { + public void run() { + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + + if (imm != null) { + showSoftInputUnchecked(SearchView.this, imm, 0); + } + } + }; + + private Runnable mUpdateDrawableStateRunnable = new Runnable() { + public void run() { + updateFocusedState(); + } + }; + + private Runnable mReleaseCursorRunnable = new Runnable() { + public void run() { + if (mSuggestionsAdapter != null && mSuggestionsAdapter instanceof SuggestionsAdapter) { + mSuggestionsAdapter.changeCursor(null); + } + } + }; + + // For voice searching + private final Intent mVoiceWebSearchIntent; + private final Intent mVoiceAppSearchIntent; + + // A weak map of drawables we've gotten from other packages, so we don't load them + // more than once. + private final WeakHashMap mOutsideDrawablesCache = + new WeakHashMap(); + + /** + * Callbacks for changes to the query text. + */ + public interface OnQueryTextListener { + + /** + * Called when the user submits the query. This could be due to a key press on the + * keyboard or due to pressing a submit button. + * The listener can override the standard behavior by returning true + * to indicate that it has handled the submit request. Otherwise return false to + * let the SearchView handle the submission by launching any associated intent. + * + * @param query the query text that is to be submitted + * + * @return true if the query has been handled by the listener, false to let the + * SearchView perform the default action. + */ + boolean onQueryTextSubmit(String query); + + /** + * Called when the query text is changed by the user. + * + * @param newText the new content of the query text field. + * + * @return false if the SearchView should perform the default action of showing any + * suggestions if available, true if the action was handled by the listener. + */ + boolean onQueryTextChange(String newText); + } + + public interface OnCloseListener { + + /** + * The user is attempting to close the SearchView. + * + * @return true if the listener wants to override the default behavior of clearing the + * text field and dismissing it, false otherwise. + */ + boolean onClose(); + } + + /** + * Callback interface for selection events on suggestions. These callbacks + * are only relevant when a SearchableInfo has been specified by {@link #setSearchableInfo}. + */ + public interface OnSuggestionListener { + + /** + * Called when a suggestion was selected by navigating to it. + * @param position the absolute position in the list of suggestions. + * + * @return true if the listener handles the event and wants to override the default + * behavior of possibly rewriting the query based on the selected item, false otherwise. + */ + boolean onSuggestionSelect(int position); + + /** + * Called when a suggestion was clicked. + * @param position the absolute position of the clicked item in the list of suggestions. + * + * @return true if the listener handles the event and wants to override the default + * behavior of launching any intent or submitting a search query specified on that item. + * Return false otherwise. + */ + boolean onSuggestionClick(int position); + } + + public SearchView(Context context) { + this(context, null); + } + + public SearchView(Context context, AttributeSet attrs) { + super(context, attrs); + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) { + throw new IllegalStateException("SearchView is API 8+ only."); + } + + LayoutInflater inflater = (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.abs__search_view, this, true); + + mSearchButton = findViewById(R.id.abs__search_button); + mQueryTextView = (SearchAutoComplete) findViewById(R.id.abs__search_src_text); + mQueryTextView.setSearchView(this); + + mSearchEditFrame = findViewById(R.id.abs__search_edit_frame); + mSearchPlate = findViewById(R.id.abs__search_plate); + mSubmitArea = findViewById(R.id.abs__submit_area); + mSubmitButton = findViewById(R.id.abs__search_go_btn); + mCloseButton = (ImageView) findViewById(R.id.abs__search_close_btn); + mVoiceButton = findViewById(R.id.abs__search_voice_btn); + mSearchHintIcon = (ImageView) findViewById(R.id.abs__search_mag_icon); + + mSearchButton.setOnClickListener(mOnClickListener); + mCloseButton.setOnClickListener(mOnClickListener); + mSubmitButton.setOnClickListener(mOnClickListener); + mVoiceButton.setOnClickListener(mOnClickListener); + mQueryTextView.setOnClickListener(mOnClickListener); + + mQueryTextView.addTextChangedListener(mTextWatcher); + mQueryTextView.setOnEditorActionListener(mOnEditorActionListener); + mQueryTextView.setOnItemClickListener(mOnItemClickListener); + mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener); + mQueryTextView.setOnKeyListener(mTextKeyListener); + // Inform any listener of focus changes + mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() { + + public void onFocusChange(View v, boolean hasFocus) { + if (mOnQueryTextFocusChangeListener != null) { + mOnQueryTextFocusChangeListener.onFocusChange(SearchView.this, hasFocus); + } + } + }); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SherlockSearchView, 0, 0); + setIconifiedByDefault(a.getBoolean(R.styleable.SherlockSearchView_iconifiedByDefault, true)); + int maxWidth = a.getDimensionPixelSize(R.styleable.SherlockSearchView_android_maxWidth, -1); + if (maxWidth != -1) { + setMaxWidth(maxWidth); + } + CharSequence queryHint = a.getText(R.styleable.SherlockSearchView_queryHint); + if (!TextUtils.isEmpty(queryHint)) { + setQueryHint(queryHint); + } + int imeOptions = a.getInt(R.styleable.SherlockSearchView_android_imeOptions, -1); + if (imeOptions != -1) { + setImeOptions(imeOptions); + } + int inputType = a.getInt(R.styleable.SherlockSearchView_android_inputType, -1); + if (inputType != -1) { + setInputType(inputType); + } + + a.recycle(); + + boolean focusable = true; + + a = context.obtainStyledAttributes(attrs, R.styleable.SherlockView, 0, 0); + focusable = a.getBoolean(R.styleable.SherlockView_android_focusable, focusable); + a.recycle(); + setFocusable(focusable); + + // Save voice intent for later queries/launching + mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); + mVoiceWebSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mVoiceWebSearchIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH); + + mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); + mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor()); + if (mDropDownAnchor != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + adjustDropDownSizeAndPosition(); + } + }); + } else { + mDropDownAnchor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override public void onGlobalLayout() { + adjustDropDownSizeAndPosition(); + } + }); + } + } + + updateViewsVisibility(mIconifiedByDefault); + updateQueryHint(); + } + + /** + * Sets the SearchableInfo for this SearchView. Properties in the SearchableInfo are used + * to display labels, hints, suggestions, create intents for launching search results screens + * and controlling other affordances such as a voice button. + * + * @param searchable a SearchableInfo can be retrieved from the SearchManager, for a specific + * activity or a global search provider. + */ + public void setSearchableInfo(SearchableInfo searchable) { + mSearchable = searchable; + if (mSearchable != null) { + updateSearchAutoComplete(); + updateQueryHint(); + } + // Cache the voice search capability + mVoiceButtonEnabled = hasVoiceSearch(); + + if (mVoiceButtonEnabled) { + // Disable the microphone on the keyboard, as a mic is displayed near the text box + // TODO: use imeOptions to disable voice input when the new API will be available + mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE); + } + updateViewsVisibility(isIconified()); + } + + /** + * Sets the APP_DATA for legacy SearchDialog use. + * @param appSearchData bundle provided by the app when launching the search dialog + * @hide + */ + public void setAppSearchData(Bundle appSearchData) { + mAppSearchData = appSearchData; + } + + /** + * Sets the IME options on the query text field. + * + * @see TextView#setImeOptions(int) + * @param imeOptions the options to set on the query text field + * + * @attr ref android.R.styleable#SearchView_imeOptions + */ + public void setImeOptions(int imeOptions) { + mQueryTextView.setImeOptions(imeOptions); + } + + /** + * Returns the IME options set on the query text field. + * @return the ime options + * @see TextView#setImeOptions(int) + * + * @attr ref android.R.styleable#SearchView_imeOptions + */ + public int getImeOptions() { + return mQueryTextView.getImeOptions(); + } + + /** + * Sets the input type on the query text field. + * + * @see TextView#setInputType(int) + * @param inputType the input type to set on the query text field + * + * @attr ref android.R.styleable#SearchView_inputType + */ + public void setInputType(int inputType) { + mQueryTextView.setInputType(inputType); + } + + /** + * Returns the input type set on the query text field. + * @return the input type + * + * @attr ref android.R.styleable#SearchView_inputType + */ + public int getInputType() { + return mQueryTextView.getInputType(); + } + + /** @hide */ + @Override + public boolean requestFocus(int direction, Rect previouslyFocusedRect) { + // Don't accept focus if in the middle of clearing focus + if (mClearingFocus) return false; + // Check if SearchView is focusable. + if (!isFocusable()) return false; + // If it is not iconified, then give the focus to the text field + if (!isIconified()) { + boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect); + if (result) { + updateViewsVisibility(false); + } + return result; + } else { + return super.requestFocus(direction, previouslyFocusedRect); + } + } + + /** @hide */ + @Override + public void clearFocus() { + mClearingFocus = true; + setImeVisibility(false); + super.clearFocus(); + mQueryTextView.clearFocus(); + mClearingFocus = false; + } + + /** + * Sets a listener for user actions within the SearchView. + * + * @param listener the listener object that receives callbacks when the user performs + * actions in the SearchView such as clicking on buttons or typing a query. + */ + public void setOnQueryTextListener(OnQueryTextListener listener) { + mOnQueryChangeListener = listener; + } + + /** + * Sets a listener to inform when the user closes the SearchView. + * + * @param listener the listener to call when the user closes the SearchView. + */ + public void setOnCloseListener(OnCloseListener listener) { + mOnCloseListener = listener; + } + + /** + * Sets a listener to inform when the focus of the query text field changes. + * + * @param listener the listener to inform of focus changes. + */ + public void setOnQueryTextFocusChangeListener(OnFocusChangeListener listener) { + mOnQueryTextFocusChangeListener = listener; + } + + /** + * Sets a listener to inform when a suggestion is focused or clicked. + * + * @param listener the listener to inform of suggestion selection events. + */ + public void setOnSuggestionListener(OnSuggestionListener listener) { + mOnSuggestionListener = listener; + } + + /** + * Sets a listener to inform when the search button is pressed. This is only + * relevant when the text field is not visible by default. Calling {@link #setIconified + * setIconified(false)} can also cause this listener to be informed. + * + * @param listener the listener to inform when the search button is clicked or + * the text field is programmatically de-iconified. + */ + public void setOnSearchClickListener(OnClickListener listener) { + mOnSearchClickListener = listener; + } + + /** + * Returns the query string currently in the text field. + * + * @return the query string + */ + public CharSequence getQuery() { + return mQueryTextView.getText(); + } + + /** + * Sets a query string in the text field and optionally submits the query as well. + * + * @param query the query string. This replaces any query text already present in the + * text field. + * @param submit whether to submit the query right now or only update the contents of + * text field. + */ + public void setQuery(CharSequence query, boolean submit) { + mQueryTextView.setText(query); + if (query != null) { + mQueryTextView.setSelection(mQueryTextView.length()); + mUserQuery = query; + } + + // If the query is not empty and submit is requested, submit the query + if (submit && !TextUtils.isEmpty(query)) { + onSubmitQuery(); + } + } + + /** + * Sets the hint text to display in the query text field. This overrides any hint specified + * in the SearchableInfo. + * + * @param hint the hint text to display + * + * @attr ref android.R.styleable#SearchView_queryHint + */ + public void setQueryHint(CharSequence hint) { + mQueryHint = hint; + updateQueryHint(); + } + + /** + * Gets the hint text to display in the query text field. + * @return the query hint text, if specified, null otherwise. + * + * @attr ref android.R.styleable#SearchView_queryHint + */ + public CharSequence getQueryHint() { + if (mQueryHint != null) { + return mQueryHint; + } else if (mSearchable != null) { + CharSequence hint = null; + int hintId = mSearchable.getHintId(); + if (hintId != 0) { + hint = getContext().getString(hintId); + } + return hint; + } + return null; + } + + /** + * Sets the default or resting state of the search field. If true, a single search icon is + * shown by default and expands to show the text field and other buttons when pressed. Also, + * if the default state is iconified, then it collapses to that state when the close button + * is pressed. Changes to this property will take effect immediately. + * + *

The default value is true.

+ * + * @param iconified whether the search field should be iconified by default + * + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + */ + public void setIconifiedByDefault(boolean iconified) { + if (mIconifiedByDefault == iconified) return; + mIconifiedByDefault = iconified; + updateViewsVisibility(iconified); + updateQueryHint(); + } + + /** + * Returns the default iconified state of the search field. + * @return + * + * @attr ref android.R.styleable#SearchView_iconifiedByDefault + */ + public boolean isIconfiedByDefault() { + return mIconifiedByDefault; + } + + /** + * Iconifies or expands the SearchView. Any query text is cleared when iconified. This is + * a temporary state and does not override the default iconified state set by + * {@link #setIconifiedByDefault(boolean)}. If the default state is iconified, then + * a false here will only be valid until the user closes the field. And if the default + * state is expanded, then a true here will only clear the text field and not close it. + * + * @param iconify a true value will collapse the SearchView to an icon, while a false will + * expand it. + */ + public void setIconified(boolean iconify) { + if (iconify) { + onCloseClicked(); + } else { + onSearchClicked(); + } + } + + /** + * Returns the current iconified state of the SearchView. + * + * @return true if the SearchView is currently iconified, false if the search field is + * fully visible. + */ + public boolean isIconified() { + return mIconified; + } + + /** + * Enables showing a submit button when the query is non-empty. In cases where the SearchView + * is being used to filter the contents of the current activity and doesn't launch a separate + * results activity, then the submit button should be disabled. + * + * @param enabled true to show a submit button for submitting queries, false if a submit + * button is not required. + */ + public void setSubmitButtonEnabled(boolean enabled) { + mSubmitButtonEnabled = enabled; + updateViewsVisibility(isIconified()); + } + + /** + * Returns whether the submit button is enabled when necessary or never displayed. + * + * @return whether the submit button is enabled automatically when necessary + */ + public boolean isSubmitButtonEnabled() { + return mSubmitButtonEnabled; + } + + /** + * Specifies if a query refinement button should be displayed alongside each suggestion + * or if it should depend on the flags set in the individual items retrieved from the + * suggestions provider. Clicking on the query refinement button will replace the text + * in the query text field with the text from the suggestion. This flag only takes effect + * if a SearchableInfo has been specified with {@link #setSearchableInfo(SearchableInfo)} + * and not when using a custom adapter. + * + * @param enable true if all items should have a query refinement button, false if only + * those items that have a query refinement flag set should have the button. + * + * @see SearchManager#SUGGEST_COLUMN_FLAGS + * @see SearchManager#FLAG_QUERY_REFINEMENT + */ + public void setQueryRefinementEnabled(boolean enable) { + mQueryRefinement = enable; + if (mSuggestionsAdapter instanceof SuggestionsAdapter) { + ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement( + enable ? SuggestionsAdapter.REFINE_ALL : SuggestionsAdapter.REFINE_BY_ENTRY); + } + } + + /** + * Returns whether query refinement is enabled for all items or only specific ones. + * @return true if enabled for all items, false otherwise. + */ + public boolean isQueryRefinementEnabled() { + return mQueryRefinement; + } + + /** + * You can set a custom adapter if you wish. Otherwise the default adapter is used to + * display the suggestions from the suggestions provider associated with the SearchableInfo. + * + * @see #setSearchableInfo(SearchableInfo) + */ + public void setSuggestionsAdapter(CursorAdapter adapter) { + mSuggestionsAdapter = adapter; + + mQueryTextView.setAdapter(mSuggestionsAdapter); + } + + /** + * Returns the adapter used for suggestions, if any. + * @return the suggestions adapter + */ + public CursorAdapter getSuggestionsAdapter() { + return mSuggestionsAdapter; + } + + /** + * Makes the view at most this many pixels wide + * + * @attr ref android.R.styleable#SearchView_maxWidth + */ + public void setMaxWidth(int maxpixels) { + mMaxWidth = maxpixels; + + requestLayout(); + } + + /** + * Gets the specified maximum width in pixels, if set. Returns zero if + * no maximum width was specified. + * @return the maximum width of the view + * + * @attr ref android.R.styleable#SearchView_maxWidth + */ + public int getMaxWidth() { + return mMaxWidth; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Let the standard measurements take effect in iconified state. + if (isIconified()) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + return; + } + + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + + switch (widthMode) { + case MeasureSpec.AT_MOST: + // If there is an upper limit, don't exceed maximum width (explicit or implicit) + if (mMaxWidth > 0) { + width = Math.min(mMaxWidth, width); + } else { + width = Math.min(getPreferredWidth(), width); + } + break; + case MeasureSpec.EXACTLY: + // If an exact width is specified, still don't exceed any specified maximum width + if (mMaxWidth > 0) { + width = Math.min(mMaxWidth, width); + } + break; + case MeasureSpec.UNSPECIFIED: + // Use maximum width, if specified, else preferred width + width = mMaxWidth > 0 ? mMaxWidth : getPreferredWidth(); + break; + } + widthMode = MeasureSpec.EXACTLY; + super.onMeasure(MeasureSpec.makeMeasureSpec(width, widthMode), heightMeasureSpec); + } + + private int getPreferredWidth() { + return getContext().getResources() + .getDimensionPixelSize(R.dimen.abs__search_view_preferred_width); + } + + private void updateViewsVisibility(final boolean collapsed) { + mIconified = collapsed; + // Visibility of views that are visible when collapsed + final int visCollapsed = collapsed ? VISIBLE : GONE; + // Is there text in the query + final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); + + mSearchButton.setVisibility(visCollapsed); + updateSubmitButton(hasText); + mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); + mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE); + updateCloseButton(); + updateVoiceButton(!hasText); + updateSubmitArea(); + } + + private boolean hasVoiceSearch() { + if (mSearchable != null && mSearchable.getVoiceSearchEnabled()) { + Intent testIntent = null; + if (mSearchable.getVoiceSearchLaunchWebSearch()) { + testIntent = mVoiceWebSearchIntent; + } else if (mSearchable.getVoiceSearchLaunchRecognizer()) { + testIntent = mVoiceAppSearchIntent; + } + if (testIntent != null) { + ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent, + PackageManager.MATCH_DEFAULT_ONLY); + return ri != null; + } + } + return false; + } + + private boolean isSubmitAreaEnabled() { + return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified(); + } + + private void updateSubmitButton(boolean hasText) { + int visibility = GONE; + if (mSubmitButtonEnabled && isSubmitAreaEnabled() && hasFocus() + && (hasText || !mVoiceButtonEnabled)) { + visibility = VISIBLE; + } + mSubmitButton.setVisibility(visibility); + } + + private void updateSubmitArea() { + int visibility = GONE; + if (isSubmitAreaEnabled() + && (mSubmitButton.getVisibility() == VISIBLE + || mVoiceButton.getVisibility() == VISIBLE)) { + visibility = VISIBLE; + } + mSubmitArea.setVisibility(visibility); + } + + private void updateCloseButton() { + final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); + // Should we show the close button? It is not shown if there's no focus, + // field is not iconified by default and there is no text in it. + final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView); + mCloseButton.setVisibility(showClose ? VISIBLE : GONE); + mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); + } + + private void postUpdateFocusedState() { + post(mUpdateDrawableStateRunnable); + } + + private void updateFocusedState() { + boolean focused = mQueryTextView.hasFocus(); + mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + invalidate(); + } + + @Override + protected void onDetachedFromWindow() { + removeCallbacks(mUpdateDrawableStateRunnable); + post(mReleaseCursorRunnable); + super.onDetachedFromWindow(); + } + + private void setImeVisibility(final boolean visible) { + if (visible) { + post(mShowImeRunnable); + } else { + removeCallbacks(mShowImeRunnable); + InputMethodManager imm = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + + if (imm != null) { + imm.hideSoftInputFromWindow(getWindowToken(), 0); + } + } + } + + /** + * Called by the SuggestionsAdapter + * @hide + */ + /* package */void onQueryRefine(CharSequence queryText) { + setQuery(queryText); + } + + private final OnClickListener mOnClickListener = new OnClickListener() { + + public void onClick(View v) { + if (v == mSearchButton) { + onSearchClicked(); + } else if (v == mCloseButton) { + onCloseClicked(); + } else if (v == mSubmitButton) { + onSubmitQuery(); + } else if (v == mVoiceButton) { + onVoiceClicked(); + } else if (v == mQueryTextView) { + forceSuggestionQuery(); + } + } + }; + + /** + * Handles the key down event for dealing with action keys. + * + * @param keyCode This is the keycode of the typed key, and is the same value as + * found in the KeyEvent parameter. + * @param event The complete event record for the typed key + * + * @return true if the event was handled here, or false if not. + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (mSearchable == null) { + return false; + } + + // if it's an action specified by the searchable activity, launch the + // entered query with the action key + // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + // TODO if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) { + // TODO launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView.getText() + // TODO .toString()); + // TODO return true; + // TODO } + + return super.onKeyDown(keyCode, event); + } + + /** + * React to the user typing "enter" or other hardwired keys while typing in + * the search box. This handles these special keys while the edit box has + * focus. + */ + View.OnKeyListener mTextKeyListener = new View.OnKeyListener() { + public boolean onKey(View v, int keyCode, KeyEvent event) { + // guard against possible race conditions + if (mSearchable == null) { + return false; + } + + if (DBG) { + Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event + "), selection: " + + mQueryTextView.getListSelection()); + } + + // If a suggestion is selected, handle enter, search key, and action keys + // as presses on the selected suggestion + if (mQueryTextView.isPopupShowing() + && mQueryTextView.getListSelection() != ListView.INVALID_POSITION) { + return onSuggestionsKey(v, keyCode, event); + } + + // If there is text in the query box, handle enter, and action keys + // The search key is handled by the dialog's onKeyDown(). + if (!mQueryTextView.isEmpty() && KeyEventCompat.hasNoModifiers(event)) { + if (event.getAction() == KeyEvent.ACTION_UP) { + if (keyCode == KeyEvent.KEYCODE_ENTER) { + v.cancelLongPress(); + + // Launch as a regular search. + launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText() + .toString()); + return true; + } + } + if (event.getAction() == KeyEvent.ACTION_DOWN) { + // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + // TODO if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) { + // TODO launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView + // TODO .getText().toString()); + // TODO return true; + // TODO } + } + } + return false; + } + }; + + /** + * React to the user typing while in the suggestions list. First, check for + * action keys. If not handled, try refocusing regular characters into the + * EditText. + */ + private boolean onSuggestionsKey(View v, int keyCode, KeyEvent event) { + // guard against possible race conditions (late arrival after dismiss) + if (mSearchable == null) { + return false; + } + if (mSuggestionsAdapter == null) { + return false; + } + if (event.getAction() == KeyEvent.ACTION_DOWN && KeyEventCompat.hasNoModifiers(event)) { + // First, check for enter or search (both of which we'll treat as a + // "click") + if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH + || keyCode == KeyEvent.KEYCODE_TAB) { + int position = mQueryTextView.getListSelection(); + return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null); + } + + // Next, check for left/right moves, which we use to "return" the + // user to the edit view + if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) { + // give "focus" to text editor, with cursor at the beginning if + // left key, at end if right key + // TODO: Reverse left/right for right-to-left languages, e.g. + // Arabic + int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView + .length(); + mQueryTextView.setSelection(selPoint); + mQueryTextView.setListSelection(0); + mQueryTextView.clearListSelection(); + ensureImeVisible(mQueryTextView, true); + + return true; + } + + // Next, check for an "up and out" move + if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection()) { + // TODO: restoreUserQuery(); + // let ACTV complete the move + return false; + } + + // Next, check for an "action key" + // TODO SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode); + // TODO if ((actionKey != null) + // TODO && ((actionKey.getSuggestActionMsg() != null) || (actionKey + // TODO .getSuggestActionMsgColumn() != null))) { + // TODO // launch suggestion using action key column + // TODO int position = mQueryTextView.getListSelection(); + // TODO if (position != ListView.INVALID_POSITION) { + // TODO Cursor c = mSuggestionsAdapter.getCursor(); + // TODO if (c.moveToPosition(position)) { + // TODO final String actionMsg = getActionKeyMessage(c, actionKey); + // TODO if (actionMsg != null && (actionMsg.length() > 0)) { + // TODO return onItemClicked(position, keyCode, actionMsg); + // TODO } + // TODO } + // TODO } + // TODO } + } + return false; + } + + /** + * For a given suggestion and a given cursor row, get the action message. If + * not provided by the specific row/column, also check for a single + * definition (for the action key). + * + * @param c The cursor providing suggestions + * @param actionKey The actionkey record being examined + * + * @return Returns a string, or null if no action key message for this + * suggestion + */ + // TODO private static String getActionKeyMessage(Cursor c, SearchableInfo.ActionKeyInfo actionKey) { + // TODO String result = null; + // TODO // check first in the cursor data, for a suggestion-specific message + // TODO final String column = actionKey.getSuggestActionMsgColumn(); + // TODO if (column != null) { + // TODO result = SuggestionsAdapter.getColumnString(c, column); + // TODO } + // TODO // If the cursor didn't give us a message, see if there's a single + // TODO // message defined + // TODO // for the actionkey (for all suggestions) + // TODO if (result == null) { + // TODO result = actionKey.getSuggestActionMsg(); + // TODO } + // TODO return result; + // TODO } + + private int getSearchIconId() { + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(R.attr.searchViewSearchIcon, + outValue, true); + return outValue.resourceId; + } + + private CharSequence getDecoratedHint(CharSequence hintText) { + // If the field is always expanded, then don't add the search icon to the hint + if (!mIconifiedByDefault) return hintText; + + SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon + ssb.append(hintText); + Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId()); + int textSize = (int) (mQueryTextView.getTextSize() * 1.25); + searchIcon.setBounds(0, 0, textSize, textSize); + ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return ssb; + } + + private void updateQueryHint() { + if (mQueryHint != null) { + mQueryTextView.setHint(getDecoratedHint(mQueryHint)); + } else if (mSearchable != null) { + CharSequence hint = null; + int hintId = mSearchable.getHintId(); + if (hintId != 0) { + hint = getContext().getString(hintId); + } + if (hint != null) { + mQueryTextView.setHint(getDecoratedHint(hint)); + } + } else { + mQueryTextView.setHint(getDecoratedHint("")); + } + } + + /** + * Updates the auto-complete text view. + */ + private void updateSearchAutoComplete() { + // TODO mQueryTextView.setDropDownAnimationStyle(0); // no animation + mQueryTextView.setThreshold(mSearchable.getSuggestThreshold()); + mQueryTextView.setImeOptions(mSearchable.getImeOptions()); + int inputType = mSearchable.getInputType(); + // We only touch this if the input type is set up for text (which it almost certainly + // should be, in the case of search!) + if ((inputType & InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) { + // The existence of a suggestions authority is the proxy for "suggestions + // are available here" + inputType &= ~InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; + if (mSearchable.getSuggestAuthority() != null) { + inputType |= InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE; + // TYPE_TEXT_FLAG_AUTO_COMPLETE means that the text editor is performing + // auto-completion based on its own semantics, which it will present to the user + // as they type. This generally means that the input method should not show its + // own candidates, and the spell checker should not be in action. The text editor + // supplies its candidates by calling InputMethodManager.displayCompletions(), + // which in turn will call InputMethodSession.displayCompletions(). + inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + } + } + mQueryTextView.setInputType(inputType); + if (mSuggestionsAdapter != null) { + mSuggestionsAdapter.changeCursor(null); + } + // attach the suggestions adapter, if suggestions are available + // The existence of a suggestions authority is the proxy for "suggestions available here" + if (mSearchable.getSuggestAuthority() != null) { + mSuggestionsAdapter = new SuggestionsAdapter(getContext(), + this, mSearchable, mOutsideDrawablesCache); + mQueryTextView.setAdapter(mSuggestionsAdapter); + ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement( + mQueryRefinement ? SuggestionsAdapter.REFINE_ALL + : SuggestionsAdapter.REFINE_BY_ENTRY); + } + } + + /** + * Update the visibility of the voice button. There are actually two voice search modes, + * either of which will activate the button. + * @param empty whether the search query text field is empty. If it is, then the other + * criteria apply to make the voice button visible. + */ + private void updateVoiceButton(boolean empty) { + int visibility = GONE; + if (mVoiceButtonEnabled && !isIconified() && empty) { + visibility = VISIBLE; + mSubmitButton.setVisibility(GONE); + } + mVoiceButton.setVisibility(visibility); + } + + private final OnEditorActionListener mOnEditorActionListener = new OnEditorActionListener() { + + /** + * Called when the input method default action key is pressed. + */ + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + onSubmitQuery(); + return true; + } + }; + + private void onTextChanged(CharSequence newText) { + CharSequence text = mQueryTextView.getText(); + mUserQuery = text; + boolean hasText = !TextUtils.isEmpty(text); + updateSubmitButton(hasText); + updateVoiceButton(!hasText); + updateCloseButton(); + updateSubmitArea(); + if (mOnQueryChangeListener != null && !TextUtils.equals(newText, mOldQueryText)) { + mOnQueryChangeListener.onQueryTextChange(newText.toString()); + } + mOldQueryText = newText.toString(); + } + + private void onSubmitQuery() { + CharSequence query = mQueryTextView.getText(); + if (query != null && TextUtils.getTrimmedLength(query) > 0) { + if (mOnQueryChangeListener == null + || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) { + if (mSearchable != null) { + launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString()); + setImeVisibility(false); + } + dismissSuggestions(); + } + } + } + + private void dismissSuggestions() { + mQueryTextView.dismissDropDown(); + } + + private void onCloseClicked() { + CharSequence text = mQueryTextView.getText(); + if (TextUtils.isEmpty(text)) { + if (mIconifiedByDefault) { + // If the app doesn't override the close behavior + if (mOnCloseListener == null || !mOnCloseListener.onClose()) { + // hide the keyboard and remove focus + clearFocus(); + // collapse the search field + updateViewsVisibility(true); + } + } + } else { + mQueryTextView.setText(""); + mQueryTextView.requestFocus(); + setImeVisibility(true); + } + + } + + private void onSearchClicked() { + updateViewsVisibility(false); + mQueryTextView.requestFocus(); + setImeVisibility(true); + if (mOnSearchClickListener != null) { + mOnSearchClickListener.onClick(this); + } + } + + private void onVoiceClicked() { + // guard against possible race conditions + if (mSearchable == null) { + return; + } + SearchableInfo searchable = mSearchable; + try { + if (searchable.getVoiceSearchLaunchWebSearch()) { + Intent webSearchIntent = createVoiceWebSearchIntent(mVoiceWebSearchIntent, + searchable); + getContext().startActivity(webSearchIntent); + } else if (searchable.getVoiceSearchLaunchRecognizer()) { + Intent appSearchIntent = createVoiceAppSearchIntent(mVoiceAppSearchIntent, + searchable); + getContext().startActivity(appSearchIntent); + } + } catch (ActivityNotFoundException e) { + // Should not happen, since we check the availability of + // voice search before showing the button. But just in case... + Log.w(LOG_TAG, "Could not find voice search activity"); + } + } + + void onTextFocusChanged() { + updateViewsVisibility(isIconified()); + // Delayed update to make sure that the focus has settled down and window focus changes + // don't affect it. A synchronous update was not working. + postUpdateFocusedState(); + if (mQueryTextView.hasFocus()) { + forceSuggestionQuery(); + } + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + + postUpdateFocusedState(); + } + + /** + * {@inheritDoc} + */ + @Override + public void onActionViewCollapsed() { + clearFocus(); + updateViewsVisibility(true); + mQueryTextView.setImeOptions(mCollapsedImeOptions); + mExpandedInActionView = false; + } + + /** + * {@inheritDoc} + */ + @Override + public void onActionViewExpanded() { + if (mExpandedInActionView) return; + + mExpandedInActionView = true; + mCollapsedImeOptions = mQueryTextView.getImeOptions(); + mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN); + mQueryTextView.setText(""); + setIconified(false); + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(SearchView.class.getName()); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(SearchView.class.getName()); + } + + private void adjustDropDownSizeAndPosition() { + if (mDropDownAnchor.getWidth() > 1) { + Resources res = getContext().getResources(); + int anchorPadding = mSearchPlate.getPaddingLeft(); + Rect dropDownPadding = new Rect(); + int iconOffset = mIconifiedByDefault + ? res.getDimensionPixelSize(R.dimen.abs__dropdownitem_icon_width) + + res.getDimensionPixelSize(R.dimen.abs__dropdownitem_text_padding_left) + : 0; + mQueryTextView.getDropDownBackground().getPadding(dropDownPadding); + mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset) + + anchorPadding); + mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left + + dropDownPadding.right + iconOffset - (anchorPadding)); + } + } + + private boolean onItemClicked(int position, int actionKey, String actionMsg) { + if (mOnSuggestionListener == null + || !mOnSuggestionListener.onSuggestionClick(position)) { + launchSuggestion(position, KeyEvent.KEYCODE_UNKNOWN, null); + setImeVisibility(false); + dismissSuggestions(); + return true; + } + return false; + } + + private boolean onItemSelected(int position) { + if (mOnSuggestionListener == null + || !mOnSuggestionListener.onSuggestionSelect(position)) { + rewriteQueryFromSuggestion(position); + return true; + } + return false; + } + + private final OnItemClickListener mOnItemClickListener = new OnItemClickListener() { + + /** + * Implements OnItemClickListener + */ + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (DBG) Log.d(LOG_TAG, "onItemClick() position " + position); + onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null); + } + }; + + private final OnItemSelectedListener mOnItemSelectedListener = new OnItemSelectedListener() { + + /** + * Implements OnItemSelectedListener + */ + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (DBG) Log.d(LOG_TAG, "onItemSelected() position " + position); + SearchView.this.onItemSelected(position); + } + + /** + * Implements OnItemSelectedListener + */ + public void onNothingSelected(AdapterView parent) { + if (DBG) + Log.d(LOG_TAG, "onNothingSelected()"); + } + }; + + /** + * Query rewriting. + */ + private void rewriteQueryFromSuggestion(int position) { + CharSequence oldQuery = mQueryTextView.getText(); + Cursor c = mSuggestionsAdapter.getCursor(); + if (c == null) { + return; + } + if (c.moveToPosition(position)) { + // Get the new query from the suggestion. + CharSequence newQuery = mSuggestionsAdapter.convertToString(c); + if (newQuery != null) { + // The suggestion rewrites the query. + // Update the text field, without getting new suggestions. + setQuery(newQuery); + } else { + // The suggestion does not rewrite the query, restore the user's query. + setQuery(oldQuery); + } + } else { + // We got a bad position, restore the user's query. + setQuery(oldQuery); + } + } + + /** + * Launches an intent based on a suggestion. + * + * @param position The index of the suggestion to create the intent from. + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or null if none. + * @return true if a successful launch, false if could not (e.g. bad position). + */ + private boolean launchSuggestion(int position, int actionKey, String actionMsg) { + Cursor c = mSuggestionsAdapter.getCursor(); + if ((c != null) && c.moveToPosition(position)) { + + Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg); + + // launch the intent + launchIntent(intent); + + return true; + } + return false; + } + + /** + * Launches an intent, including any special intent handling. + */ + private void launchIntent(Intent intent) { + if (intent == null) { + return; + } + try { + // If the intent was created from a suggestion, it will always have an explicit + // component here. + getContext().startActivity(intent); + } catch (RuntimeException ex) { + Log.e(LOG_TAG, "Failed launch activity: " + intent, ex); + } + } + + /** + * Sets the text in the query box, without updating the suggestions. + */ + private void setQuery(CharSequence query) { + setText(mQueryTextView, query, true); + // Move the cursor to the end + mQueryTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length()); + } + + private void launchQuerySearch(int actionKey, String actionMsg, String query) { + String action = Intent.ACTION_SEARCH; + Intent intent = createIntent(action, null, null, query, actionKey, actionMsg); + getContext().startActivity(intent); + } + + /** + * Constructs an intent from the given information and the search dialog state. + * + * @param action Intent action. + * @param data Intent data, or null. + * @param extraData Data for {@link SearchManager#EXTRA_DATA_KEY} or null. + * @param query Intent query, or null. + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or null if none. + * @return The intent. + */ + private Intent createIntent(String action, Uri data, String extraData, String query, + int actionKey, String actionMsg) { + // Now build the Intent + Intent intent = new Intent(action); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + // We need CLEAR_TOP to avoid reusing an old task that has other activities + // on top of the one we want. We don't want to do this in in-app search though, + // as it can be destructive to the activity stack. + if (data != null) { + intent.setData(data); + } + intent.putExtra(SearchManager.USER_QUERY, mUserQuery); + if (query != null) { + intent.putExtra(SearchManager.QUERY, query); + } + if (extraData != null) { + intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData); + } + if (mAppSearchData != null) { + intent.putExtra(SearchManager.APP_DATA, mAppSearchData); + } + if (actionKey != KeyEvent.KEYCODE_UNKNOWN) { + intent.putExtra(SearchManager.ACTION_KEY, actionKey); + intent.putExtra(SearchManager.ACTION_MSG, actionMsg); + } + intent.setComponent(mSearchable.getSearchActivity()); + return intent; + } + + /** + * Create and return an Intent that can launch the voice search activity for web search. + */ + private Intent createVoiceWebSearchIntent(Intent baseIntent, SearchableInfo searchable) { + Intent voiceIntent = new Intent(baseIntent); + ComponentName searchActivity = searchable.getSearchActivity(); + voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null + : searchActivity.flattenToShortString()); + return voiceIntent; + } + + /** + * Create and return an Intent that can launch the voice search activity, perform a specific + * voice transcription, and forward the results to the searchable activity. + * + * @param baseIntent The voice app search intent to start from + * @return A completely-configured intent ready to send to the voice search activity + */ + private Intent createVoiceAppSearchIntent(Intent baseIntent, SearchableInfo searchable) { + ComponentName searchActivity = searchable.getSearchActivity(); + + // create the necessary intent to set up a search-and-forward operation + // in the voice search system. We have to keep the bundle separate, + // because it becomes immutable once it enters the PendingIntent + Intent queryIntent = new Intent(Intent.ACTION_SEARCH); + queryIntent.setComponent(searchActivity); + PendingIntent pending = PendingIntent.getActivity(getContext(), 0, queryIntent, + PendingIntent.FLAG_ONE_SHOT); + + // Now set up the bundle that will be inserted into the pending intent + // when it's time to do the search. We always build it here (even if empty) + // because the voice search activity will always need to insert "QUERY" into + // it anyway. + Bundle queryExtras = new Bundle(); + + // Now build the intent to launch the voice search. Add all necessary + // extras to launch the voice recognizer, and then all the necessary extras + // to forward the results to the searchable activity + Intent voiceIntent = new Intent(baseIntent); + + // Add all of the configuration options supplied by the searchable's metadata + String languageModel = RecognizerIntent.LANGUAGE_MODEL_FREE_FORM; + String prompt = null; + String language = null; + int maxResults = 1; + + Resources resources = getResources(); + if (searchable.getVoiceLanguageModeId() != 0) { + languageModel = resources.getString(searchable.getVoiceLanguageModeId()); + } + if (searchable.getVoicePromptTextId() != 0) { + prompt = resources.getString(searchable.getVoicePromptTextId()); + } + if (searchable.getVoiceLanguageId() != 0) { + language = resources.getString(searchable.getVoiceLanguageId()); + } + if (searchable.getVoiceMaxResults() != 0) { + maxResults = searchable.getVoiceMaxResults(); + } + voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, languageModel); + voiceIntent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); + voiceIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language); + voiceIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, maxResults); + voiceIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, searchActivity == null ? null + : searchActivity.flattenToShortString()); + + // Add the values that configure forwarding the results + voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT, pending); + voiceIntent.putExtra(RecognizerIntent.EXTRA_RESULTS_PENDINGINTENT_BUNDLE, queryExtras); + + return voiceIntent; + } + + /** + * When a particular suggestion has been selected, perform the various lookups required + * to use the suggestion. This includes checking the cursor for suggestion-specific data, + * and/or falling back to the XML for defaults; It also creates REST style Uri data when + * the suggestion includes a data id. + * + * @param c The suggestions cursor, moved to the row of the user's selection + * @param actionKey The key code of the action key that was pressed, + * or {@link KeyEvent#KEYCODE_UNKNOWN} if none. + * @param actionMsg The message for the action key that was pressed, + * or null if none. + * @return An intent for the suggestion at the cursor's position. + */ + private Intent createIntentFromSuggestion(Cursor c, int actionKey, String actionMsg) { + try { + // use specific action if supplied, or default action if supplied, or fixed default + String action = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_ACTION); + + if (action == null) { + action = mSearchable.getSuggestIntentAction(); + } + if (action == null) { + action = Intent.ACTION_SEARCH; + } + + // use specific data if supplied, or default data if supplied + String data = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA); + if (data == null) { + data = mSearchable.getSuggestIntentData(); + } + // then, if an ID was provided, append it. + if (data != null) { + String id = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID); + if (id != null) { + data = data + "/" + Uri.encode(id); + } + } + Uri dataUri = (data == null) ? null : Uri.parse(data); + + String query = getColumnString(c, SearchManager.SUGGEST_COLUMN_QUERY); + String extraData = getColumnString(c, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA); + + return createIntent(action, dataUri, extraData, query, actionKey, actionMsg); + } catch (RuntimeException e ) { + int rowNum; + try { // be really paranoid now + rowNum = c.getPosition(); + } catch (RuntimeException e2 ) { + rowNum = -1; + } + Log.w(LOG_TAG, "Search suggestions cursor at row " + rowNum + + " returned exception.", e); + return null; + } + } + + private void forceSuggestionQuery() { + try { + Method before = SearchAutoComplete.class.getMethod("doBeforeTextChanged"); + Method after = SearchAutoComplete.class.getMethod("doAfterTextChanged"); + before.setAccessible(true); + after.setAccessible(true); + before.invoke(mQueryTextView); + after.invoke(mQueryTextView); + } catch (Exception e) { + // Oh well... + } + } + + static boolean isLandscapeMode(Context context) { + return context.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE; + } + + /** + * Callback to watch the text field for empty/non-empty + */ + private TextWatcher mTextWatcher = new TextWatcher() { + + public void beforeTextChanged(CharSequence s, int start, int before, int after) { } + + public void onTextChanged(CharSequence s, int start, + int before, int after) { + SearchView.this.onTextChanged(s); + } + + public void afterTextChanged(Editable s) { + } + }; + + /** + * Local subclass for AutoCompleteTextView. + * @hide + */ + public static class SearchAutoComplete extends AutoCompleteTextView { + + private int mThreshold; + private SearchView mSearchView; + + public SearchAutoComplete(Context context) { + super(context); + mThreshold = getThreshold(); + } + + public SearchAutoComplete(Context context, AttributeSet attrs) { + super(context, attrs); + mThreshold = getThreshold(); + } + + public SearchAutoComplete(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mThreshold = getThreshold(); + } + + void setSearchView(SearchView searchView) { + mSearchView = searchView; + } + + @Override + public void setThreshold(int threshold) { + super.setThreshold(threshold); + mThreshold = threshold; + } + + /** + * Returns true if the text field is empty, or contains only whitespace. + */ + private boolean isEmpty() { + return TextUtils.getTrimmedLength(getText()) == 0; + } + + /** + * We override this method to avoid replacing the query box text when a + * suggestion is clicked. + */ + @Override + protected void replaceText(CharSequence text) { + } + + /** + * We override this method to avoid an extra onItemClick being called on + * the drop-down's OnItemClickListener by + * {@link AutoCompleteTextView#onKeyUp(int, KeyEvent)} when an item is + * clicked with the trackball. + */ + @Override + public void performCompletion() { + } + + /** + * We override this method to be sure and show the soft keyboard if + * appropriate when the TextView has focus. + */ + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + + if (hasWindowFocus && mSearchView.hasFocus() && getVisibility() == VISIBLE) { + InputMethodManager inputManager = (InputMethodManager) getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInput(this, 0); + // If in landscape mode, then make sure that + // the ime is in front of the dropdown. + if (isLandscapeMode(getContext())) { + ensureImeVisible(this, true); + } + } + } + + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + mSearchView.onTextFocusChanged(); + } + + /** + * We override this method so that we can allow a threshold of zero, + * which ACTV does not. + */ + @Override + public boolean enoughToFilter() { + return mThreshold <= 0 || super.enoughToFilter(); + } + + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + // special case for the back key, we do not even try to send it + // to the drop down list but instead, consume it immediately + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } + if (event.isTracking() && !event.isCanceled()) { + mSearchView.clearFocus(); + mSearchView.setImeVisibility(false); + return true; + } + } + } + return super.onKeyPreIme(keyCode, event); + } + + } + + private static void ensureImeVisible(AutoCompleteTextView view, boolean visible) { + try { + Method method = AutoCompleteTextView.class.getMethod("ensureImeVisible", boolean.class); + method.setAccessible(true); + method.invoke(view, visible); + } catch (Exception e) { + //Oh well... + } + } + + private static void showSoftInputUnchecked(View view, InputMethodManager imm, int flags) { + try { + Method method = imm.getClass().getMethod("showSoftInputUnchecked", int.class, ResultReceiver.class); + method.setAccessible(true); + method.invoke(imm, flags, null); + } catch (Exception e) { + //Fallback to public API which hopefully does mostly the same thing + imm.showSoftInput(view, flags); + } + } + + private static void setText(AutoCompleteTextView view, CharSequence text, boolean filter) { + try { + Method method = AutoCompleteTextView.class.getMethod("setText", CharSequence.class, boolean.class); + method.setAccessible(true); + method.invoke(view, text, filter); + } catch (Exception e) { + //Fallback to public API which hopefully does mostly the same thing + view.setText(text); + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java new file mode 100644 index 000000000..83e9f0ca9 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/ShareActionProvider.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.widget; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.drawable.Drawable; +import android.util.TypedValue; +import android.view.View; + +import com.actionbarsherlock.R; +import com.actionbarsherlock.view.ActionProvider; +import com.actionbarsherlock.view.Menu; +import com.actionbarsherlock.view.MenuItem; +import com.actionbarsherlock.view.MenuItem.OnMenuItemClickListener; +import com.actionbarsherlock.view.SubMenu; +import com.actionbarsherlock.widget.ActivityChooserModel.OnChooseActivityListener; + +/** + * This is a provider for a share action. It is responsible for creating views + * that enable data sharing and also to show a sub menu with sharing activities + * if the hosting item is placed on the overflow menu. + *

+ * Here is how to use the action provider with custom backing file in a {@link MenuItem}: + *

+ *

+ *

+ * 
+ *  // In Activity#onCreateOptionsMenu
+ *  public boolean onCreateOptionsMenu(Menu menu) {
+ *      // Get the menu item.
+ *      MenuItem menuItem = menu.findItem(R.id.my_menu_item);
+ *      // Get the provider and hold onto it to set/change the share intent.
+ *      mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
+ *      // Set history different from the default before getting the action
+ *      // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
+ *      // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
+ *      // line if using the default share history file is desired.
+ *      mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
+ *      . . .
+ *  }
+ *
+ *  // Somewhere in the application.
+ *  public void doShare(Intent shareIntent) {
+ *      // When you want to share set the share intent.
+ *      mShareActionProvider.setShareIntent(shareIntent);
+ *  }
+ * 
+ * + *

+ *

+ * Note: While the sample snippet demonstrates how to use this provider + * in the context of a menu item, the use of the provider is not limited to menu items. + *

+ * + * @see ActionProvider + */ +public class ShareActionProvider extends ActionProvider { + + /** + * Listener for the event of selecting a share target. + */ + public interface OnShareTargetSelectedListener { + + /** + * Called when a share target has been selected. The client can + * decide whether to handle the intent or rely on the default + * behavior which is launching it. + *

+ * Note: Modifying the intent is not permitted and + * any changes to the latter will be ignored. + *

+ * + * @param source The source of the notification. + * @param intent The intent for launching the chosen share target. + * @return Whether the client has handled the intent. + */ + public boolean onShareTargetSelected(ShareActionProvider source, Intent intent); + } + + /** + * The default for the maximal number of activities shown in the sub-menu. + */ + private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4; + + /** + * The the maximum number activities shown in the sub-menu. + */ + private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT; + + /** + * Listener for handling menu item clicks. + */ + private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener = + new ShareMenuItemOnMenuItemClickListener(); + + /** + * The default name for storing share history. + */ + public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml"; + + /** + * Context for accessing resources. + */ + private final Context mContext; + + /** + * The name of the file with share history data. + */ + private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME; + + private OnShareTargetSelectedListener mOnShareTargetSelectedListener; + + private OnChooseActivityListener mOnChooseActivityListener; + + /** + * Creates a new instance. + * + * @param context Context for accessing resources. + */ + public ShareActionProvider(Context context) { + super(context); + mContext = context; + } + + /** + * Sets a listener to be notified when a share target has been selected. + * The listener can optionally decide to handle the selection and + * not rely on the default behavior which is to launch the activity. + *

+ * Note: If you choose the backing share history file + * you will still be notified in this callback. + *

+ * @param listener The listener. + */ + public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) { + mOnShareTargetSelectedListener = listener; + setActivityChooserPolicyIfNeeded(); + } + + /** + * {@inheritDoc} + */ + @Override + public View onCreateActionView() { + // Create the view and set its data model. + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); + ActivityChooserView activityChooserView = new ActivityChooserView(mContext); + activityChooserView.setActivityChooserModel(dataModel); + + // Lookup and set the expand action icon. + TypedValue outTypedValue = new TypedValue(); + mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true); + Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId); + activityChooserView.setExpandActivityOverflowButtonDrawable(drawable); + activityChooserView.setProvider(this); + + // Set content description. + activityChooserView.setDefaultActionButtonContentDescription( + R.string.abs__shareactionprovider_share_with_application); + activityChooserView.setExpandActivityOverflowButtonContentDescription( + R.string.abs__shareactionprovider_share_with); + + return activityChooserView; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean hasSubMenu() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + public void onPrepareSubMenu(SubMenu subMenu) { + // Clear since the order of items may change. + subMenu.clear(); + + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); + PackageManager packageManager = mContext.getPackageManager(); + + final int expandedActivityCount = dataModel.getActivityCount(); + final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount); + + // Populate the sub-menu with a sub set of the activities. + for (int i = 0; i < collapsedActivityCount; i++) { + ResolveInfo activity = dataModel.getActivity(i); + subMenu.add(0, i, i, activity.loadLabel(packageManager)) + .setIcon(activity.loadIcon(packageManager)) + .setOnMenuItemClickListener(mOnMenuItemClickListener); + } + + if (collapsedActivityCount < expandedActivityCount) { + // Add a sub-menu for showing all activities as a list item. + SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount, + collapsedActivityCount, + mContext.getString(R.string.abs__activity_chooser_view_see_all)); + for (int i = 0; i < expandedActivityCount; i++) { + ResolveInfo activity = dataModel.getActivity(i); + expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager)) + .setIcon(activity.loadIcon(packageManager)) + .setOnMenuItemClickListener(mOnMenuItemClickListener); + } + } + } + + /** + * Sets the file name of a file for persisting the share history which + * history will be used for ordering share targets. This file will be used + * for all view created by {@link #onCreateActionView()}. Defaults to + * {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to null + * if share history should not be persisted between sessions. + *

+ * Note: The history file name can be set any time, however + * only the action views created by {@link #onCreateActionView()} after setting + * the file name will be backed by the provided file. + *

+ * + * @param shareHistoryFile The share history file name. + */ + public void setShareHistoryFileName(String shareHistoryFile) { + mShareHistoryFileName = shareHistoryFile; + setActivityChooserPolicyIfNeeded(); + } + + /** + * Sets an intent with information about the share action. Here is a + * sample for constructing a share intent: + *

+ *

+     * 
+     *  Intent shareIntent = new Intent(Intent.ACTION_SEND);
+     *  shareIntent.setType("image/*");
+     *  Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
+     *  shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
+     * 
+ * + *

+ * + * @param shareIntent The share intent. + * + * @see Intent#ACTION_SEND + * @see Intent#ACTION_SEND_MULTIPLE + */ + public void setShareIntent(Intent shareIntent) { + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, + mShareHistoryFileName); + dataModel.setIntent(shareIntent); + } + + /** + * Reusable listener for handling share item clicks. + */ + private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener { + @Override + public boolean onMenuItemClick(MenuItem item) { + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, + mShareHistoryFileName); + final int itemId = item.getItemId(); + Intent launchIntent = dataModel.chooseActivity(itemId); + if (launchIntent != null) { + mContext.startActivity(launchIntent); + } + return true; + } + } + + /** + * Set the activity chooser policy of the model backed by the current + * share history file if needed which is if there is a registered callback. + */ + private void setActivityChooserPolicyIfNeeded() { + if (mOnShareTargetSelectedListener == null) { + return; + } + if (mOnChooseActivityListener == null) { + mOnChooseActivityListener = new ShareAcitivityChooserModelPolicy(); + } + ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName); + dataModel.setOnChooseActivityListener(mOnChooseActivityListener); + } + + /** + * Policy that delegates to the {@link OnShareTargetSelectedListener}, if such. + */ + private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener { + @Override + public boolean onChooseActivity(ActivityChooserModel host, Intent intent) { + if (mOnShareTargetSelectedListener != null) { + return mOnShareTargetSelectedListener.onShareTargetSelected( + ShareActionProvider.this, intent); + } + return false; + } + } +} diff --git a/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java new file mode 100644 index 000000000..bd5cbd718 --- /dev/null +++ b/libraries/ActionBarSherlock/src/com/actionbarsherlock/widget/SuggestionsAdapter.java @@ -0,0 +1,733 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.actionbarsherlock.widget; + +import android.app.SearchManager; +import android.app.SearchableInfo; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.widget.ResourceCursorAdapter; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.style.TextAppearanceSpan; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import com.actionbarsherlock.R; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.WeakHashMap; + +/** + * Provides the contents for the suggestion drop-down list. + * + * @hide + */ +class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListener { + + private static final boolean DBG = false; + private static final String LOG_TAG = "SuggestionsAdapter"; + private static final int QUERY_LIMIT = 50; + + static final int REFINE_NONE = 0; + static final int REFINE_BY_ENTRY = 1; + static final int REFINE_ALL = 2; + + private SearchManager mSearchManager; + private SearchView mSearchView; + private Context mProviderContext; + private WeakHashMap mOutsideDrawablesCache; + private boolean mClosed = false; + private int mQueryRefinement = REFINE_BY_ENTRY; + + // URL color + private ColorStateList mUrlColor; + + static final int INVALID_INDEX = -1; + + // Cached column indexes, updated when the cursor changes. + private int mText1Col = INVALID_INDEX; + private int mText2Col = INVALID_INDEX; + private int mText2UrlCol = INVALID_INDEX; + private int mIconName1Col = INVALID_INDEX; + private int mIconName2Col = INVALID_INDEX; + private int mFlagsCol = INVALID_INDEX; + + // private final Runnable mStartSpinnerRunnable; + // private final Runnable mStopSpinnerRunnable; + + /** + * The amount of time we delay in the filter when the user presses the delete key. + */ + //private static final long DELETE_KEY_POST_DELAY = 500L; + + public SuggestionsAdapter(Context context, SearchView searchView, + SearchableInfo mSearchable, WeakHashMap outsideDrawablesCache) { + super(context, + R.layout.abs__search_dropdown_item_icons_2line, + null, // no initial cursor + true); // auto-requery + mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); + mProviderContext = mContext; + mSearchView = searchView; + + mOutsideDrawablesCache = outsideDrawablesCache; + + // mStartSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(true); // TODO: + // } + // }; + // + // mStopSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(false); // TODO: + // } + // }; + + // delay 500ms when deleting +// TODO getFilter().setDelayer(new Filter.Delayer() { +// +// private int mPreviousLength = 0; +// +// public long getPostingDelay(CharSequence constraint) { +// if (constraint == null) return 0; +// +// long delay = constraint.length() < mPreviousLength ? DELETE_KEY_POST_DELAY : 0; +// mPreviousLength = constraint.length(); +// return delay; +// } +// }); + } + + /** + * Enables query refinement for all suggestions. This means that an additional icon + * will be shown for each entry. When clicked, the suggested text on that line will be + * copied to the query text field. + *

+ * + * @param refineWhat which queries to refine. Possible values are {@link #REFINE_NONE}, + * {@link #REFINE_BY_ENTRY}, and {@link #REFINE_ALL}. + */ + public void setQueryRefinement(int refineWhat) { + mQueryRefinement = refineWhat; + } + + /** + * Returns the current query refinement preference. + * @return value of query refinement preference + */ + public int getQueryRefinement() { + return mQueryRefinement; + } + + /** + * Overridden to always return false, since we cannot be sure that + * suggestion sources return stable IDs. + */ + @Override + public boolean hasStableIds() { + return false; + } + + /** + * Use the search suggestions provider to obtain a live cursor. This will be called + * in a worker thread, so it's OK if the query is slow (e.g. round trip for suggestions). + * The results will be processed in the UI thread and changeCursor() will be called. + */ + @Override + public Cursor runQueryOnBackgroundThread(CharSequence constraint) { + if (DBG) Log.d(LOG_TAG, "runQueryOnBackgroundThread(" + constraint + ")"); + String query = (constraint == null) ? "" : constraint.toString(); + /** + * for in app search we show the progress spinner until the cursor is returned with + * the results. + */ + Cursor cursor = null; + if (mSearchView.getVisibility() != View.VISIBLE + || mSearchView.getWindowVisibility() != View.VISIBLE) { + return null; + } + //mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO: + try { + cursor = getSuggestions(query, QUERY_LIMIT); + // trigger fill window so the spinner stays up until the results are copied over and + // closer to being ready + if (cursor != null) { + cursor.getCount(); + return cursor; + } + } catch (RuntimeException e) { + Log.w(LOG_TAG, "Search suggestions query threw an exception.", e); + } + // If cursor is null or an exception was thrown, stop the spinner and return null. + // changeCursor doesn't get called if cursor is null + // mSearchView.getWindow().getDecorView().post(mStopSpinnerRunnable); // TODO: + return null; + } + + public Cursor getSuggestions(String query, int limit) { + Uri.Builder uriBuilder = new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .query("") // TODO: Remove, workaround for a bug in Uri.writeToParcel() + .fragment(""); // TODO: Remove, workaround for a bug in Uri.writeToParcel() + + // append standard suggestion query path + uriBuilder.appendPath(SearchManager.SUGGEST_URI_PATH_QUERY); + + // inject query, either as selection args or inline + uriBuilder.appendPath(query); + + if (limit > 0) { + uriBuilder.appendQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT, String.valueOf(limit)); + } + + Uri uri = uriBuilder.build(); + + // finally, make the query + return mContext.getContentResolver().query(uri, null, null, null, null); + } + + public void close() { + if (DBG) Log.d(LOG_TAG, "close()"); + changeCursor(null); + mClosed = true; + } + + @Override + public void notifyDataSetChanged() { + if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged"); + super.notifyDataSetChanged(); + + // mSearchView.onDataSetChanged(); // TODO: + + updateSpinnerState(getCursor()); + } + + @Override + public void notifyDataSetInvalidated() { + if (DBG) Log.d(LOG_TAG, "notifyDataSetInvalidated"); + super.notifyDataSetInvalidated(); + + updateSpinnerState(getCursor()); + } + + private void updateSpinnerState(Cursor cursor) { + Bundle extras = cursor != null ? cursor.getExtras() : null; + if (DBG) { + Log.d(LOG_TAG, "updateSpinnerState - extra = " + + (extras != null + ? extras.getBoolean(SearchManager.CURSOR_EXTRA_KEY_IN_PROGRESS) + : null)); + } + // Check if the Cursor indicates that the query is not complete and show the spinner + if (extras != null + && extras.getBoolean(SearchManager.CURSOR_EXTRA_KEY_IN_PROGRESS)) { + // mSearchView.getWindow().getDecorView().post(mStartSpinnerRunnable); // TODO: + return; + } + // If cursor is null or is done, stop the spinner + // mSearchView.getWindow().getDecorView().post(mStopSpinnerRunnable); // TODO: + } + + /** + * Cache columns. + */ + @Override + public void changeCursor(Cursor c) { + if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")"); + + if (mClosed) { + Log.w(LOG_TAG, "Tried to change cursor after adapter was closed."); + if (c != null) c.close(); + return; + } + + try { + super.changeCursor(c); + + if (c != null) { + mText1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_1); + mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2); + mText2UrlCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2_URL); + mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1); + mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2); + mFlagsCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FLAGS); + } + } catch (Exception e) { + Log.e(LOG_TAG, "error changing cursor and caching columns", e); + } + } + + /** + * Tags the view with cached child view look-ups. + */ + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + View v = super.newView(context, cursor, parent); + v.setTag(new ChildViewCache(v)); + return v; + } + + /** + * Cache of the child views of drop-drown list items, to avoid looking up the children + * each time the contents of a list item are changed. + */ + private final static class ChildViewCache { + public final TextView mText1; + public final TextView mText2; + public final ImageView mIcon1; + public final ImageView mIcon2; + public final ImageView mIconRefine; + + public ChildViewCache(View v) { + mText1 = (TextView) v.findViewById(android.R.id.text1); + mText2 = (TextView) v.findViewById(android.R.id.text2); + mIcon1 = (ImageView) v.findViewById(android.R.id.icon1); + mIcon2 = (ImageView) v.findViewById(android.R.id.icon2); + mIconRefine = (ImageView) v.findViewById(R.id.edit_query); + } + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + ChildViewCache views = (ChildViewCache) view.getTag(); + + int flags = 0; + if (mFlagsCol != INVALID_INDEX) { + flags = cursor.getInt(mFlagsCol); + } + if (views.mText1 != null) { + String text1 = getStringOrNull(cursor, mText1Col); + setViewText(views.mText1, text1); + } + if (views.mText2 != null) { + // First check TEXT_2_URL + CharSequence text2 = getStringOrNull(cursor, mText2UrlCol); + if (text2 != null) { + text2 = formatUrl(text2); + } else { + text2 = getStringOrNull(cursor, mText2Col); + } + + // If no second line of text is indicated, allow the first line of text + // to be up to two lines if it wants to be. + if (TextUtils.isEmpty(text2)) { + if (views.mText1 != null) { + views.mText1.setSingleLine(false); + views.mText1.setMaxLines(2); + } + } else { + if (views.mText1 != null) { + views.mText1.setSingleLine(true); + views.mText1.setMaxLines(1); + } + } + setViewText(views.mText2, text2); + } + + if (views.mIcon1 != null) { + setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE); + } + if (views.mIcon2 != null) { + setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE); + } + if (mQueryRefinement == REFINE_ALL + || (mQueryRefinement == REFINE_BY_ENTRY + && (flags & SearchManager.FLAG_QUERY_REFINEMENT) != 0)) { + views.mIconRefine.setVisibility(View.VISIBLE); + views.mIconRefine.setTag(views.mText1.getText()); + views.mIconRefine.setOnClickListener(this); + } else { + views.mIconRefine.setVisibility(View.GONE); + } + } + + public void onClick(View v) { + Object tag = v.getTag(); + if (tag instanceof CharSequence) { + mSearchView.onQueryRefine((CharSequence) tag); + } + } + + private CharSequence formatUrl(CharSequence url) { + if (mUrlColor == null) { + // Lazily get the URL color from the current theme. + TypedValue colorValue = new TypedValue(); + mContext.getTheme().resolveAttribute(R.attr.textColorSearchUrl, colorValue, true); + mUrlColor = mContext.getResources().getColorStateList(colorValue.resourceId); + } + + SpannableString text = new SpannableString(url); + text.setSpan(new TextAppearanceSpan(null, 0, 0, mUrlColor, null), + 0, url.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return text; + } + + private void setViewText(TextView v, CharSequence text) { + // Set the text even if it's null, since we need to clear any previous text. + v.setText(text); + + if (TextUtils.isEmpty(text)) { + v.setVisibility(View.GONE); + } else { + v.setVisibility(View.VISIBLE); + } + } + + private Drawable getIcon1(Cursor cursor) { + if (mIconName1Col == INVALID_INDEX) { + return null; + } + String value = cursor.getString(mIconName1Col); + Drawable drawable = getDrawableFromResourceValue(value); + if (drawable != null) { + return drawable; + } + return getDefaultIcon1(cursor); + } + + private Drawable getIcon2(Cursor cursor) { + if (mIconName2Col == INVALID_INDEX) { + return null; + } + String value = cursor.getString(mIconName2Col); + return getDrawableFromResourceValue(value); + } + + /** + * Sets the drawable in an image view, makes sure the view is only visible if there + * is a drawable. + */ + private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) { + // Set the icon even if the drawable is null, since we need to clear any + // previous icon. + v.setImageDrawable(drawable); + + if (drawable == null) { + v.setVisibility(nullVisibility); + } else { + v.setVisibility(View.VISIBLE); + + // This is a hack to get any animated drawables (like a 'working' spinner) + // to animate. You have to setVisible true on an AnimationDrawable to get + // it to start animating, but it must first have been false or else the + // call to setVisible will be ineffective. We need to clear up the story + // about animated drawables in the future, see http://b/1878430. + drawable.setVisible(false, false); + drawable.setVisible(true, false); + } + } + + /** + * Gets the text to show in the query field when a suggestion is selected. + * + * @param cursor The Cursor to read the suggestion data from. The Cursor should already + * be moved to the suggestion that is to be read from. + * @return The text to show, or null if the query should not be + * changed when selecting this suggestion. + */ + @Override + public CharSequence convertToString(Cursor cursor) { + if (cursor == null) { + return null; + } + + String query = getColumnString(cursor, SearchManager.SUGGEST_COLUMN_QUERY); + if (query != null) { + return query; + } + + return null; + } + + /** + * This method is overridden purely to provide a bit of protection against + * flaky content providers. + * + * @see android.widget.ListAdapter#getView(int, View, ViewGroup) + */ + @Override + public View getView(int position, View convertView, ViewGroup parent) { + try { + return super.getView(position, convertView, parent); + } catch (RuntimeException e) { + Log.w(LOG_TAG, "Search suggestions cursor threw exception.", e); + // Put exception string in item title + View v = newView(mContext, mCursor, parent); + if (v != null) { + ChildViewCache views = (ChildViewCache) v.getTag(); + TextView tv = views.mText1; + tv.setText(e.toString()); + } + return v; + } + } + + /** + * Gets a drawable given a value provided by a suggestion provider. + * + * This value could be just the string value of a resource id + * (e.g., "2130837524"), in which case we will try to retrieve a drawable from + * the provider's resources. If the value is not an integer, it is + * treated as a Uri and opened with + * {@link ContentResolver#openOutputStream(android.net.Uri, String)}. + * + * All resources and URIs are read using the suggestion provider's context. + * + * If the string is not formatted as expected, or no drawable can be found for + * the provided value, this method returns null. + * + * @param drawableId a string like "2130837524", + * "android.resource://com.android.alarmclock/2130837524", + * or "content://contacts/photos/253". + * @return a Drawable, or null if none found + */ + private Drawable getDrawableFromResourceValue(String drawableId) { + if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) { + return null; + } + try { + // First, see if it's just an integer + int resourceId = Integer.parseInt(drawableId); + // It's an int, look for it in the cache + String drawableUri = ContentResolver.SCHEME_ANDROID_RESOURCE + + "://" + mProviderContext.getPackageName() + "/" + resourceId; + // Must use URI as cache key, since ints are app-specific + Drawable drawable = checkIconCache(drawableUri); + if (drawable != null) { + return drawable; + } + // Not cached, find it by resource ID + drawable = mProviderContext.getResources().getDrawable(resourceId); + // Stick it in the cache, using the URI as key + storeInIconCache(drawableUri, drawable); + return drawable; + } catch (NumberFormatException nfe) { + // It's not an integer, use it as a URI + Drawable drawable = checkIconCache(drawableId); + if (drawable != null) { + return drawable; + } + Uri uri = Uri.parse(drawableId); + drawable = getDrawable(uri); + storeInIconCache(drawableId, drawable); + return drawable; + } catch (Resources.NotFoundException nfe) { + // It was an integer, but it couldn't be found, bail out + Log.w(LOG_TAG, "Icon resource not found: " + drawableId); + return null; + } + } + + /** + * Gets a drawable by URI, without using the cache. + * + * @return A drawable, or {@code null} if the drawable could not be loaded. + */ + private Drawable getDrawable(Uri uri) { + try { + String scheme = uri.getScheme(); + if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) { + // Load drawables through Resources, to get the source density information + try { + return getTheDrawable(uri); + } catch (Resources.NotFoundException ex) { + throw new FileNotFoundException("Resource does not exist: " + uri); + } + } else { + // Let the ContentResolver handle content and file URIs. + InputStream stream = mProviderContext.getContentResolver().openInputStream(uri); + if (stream == null) { + throw new FileNotFoundException("Failed to open " + uri); + } + try { + return Drawable.createFromStream(stream, null); + } finally { + try { + stream.close(); + } catch (IOException ex) { + Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex); + } + } + } + } catch (FileNotFoundException fnfe) { + Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage()); + return null; + } + } + + public Drawable getTheDrawable(Uri uri) throws FileNotFoundException { + String authority = uri.getAuthority(); + Resources r; + if (TextUtils.isEmpty(authority)) { + throw new FileNotFoundException("No authority: " + uri); + } else { + try { + r = mContext.getPackageManager().getResourcesForApplication(authority); + } catch (NameNotFoundException ex) { + throw new FileNotFoundException("No package found for authority: " + uri); + } + } + List path = uri.getPathSegments(); + if (path == null) { + throw new FileNotFoundException("No path: " + uri); + } + int len = path.size(); + int id; + if (len == 1) { + try { + id = Integer.parseInt(path.get(0)); + } catch (NumberFormatException e) { + throw new FileNotFoundException("Single path segment is not a resource ID: " + uri); + } + } else if (len == 2) { + id = r.getIdentifier(path.get(1), path.get(0), authority); + } else { + throw new FileNotFoundException("More than two path segments: " + uri); + } + if (id == 0) { + throw new FileNotFoundException("No resource found for: " + uri); + } + return r.getDrawable(id); + } + + private Drawable checkIconCache(String resourceUri) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri); + if (cached == null) { + return null; + } + if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri); + return cached.newDrawable(); + } + + private void storeInIconCache(String resourceUri, Drawable drawable) { + if (drawable != null) { + mOutsideDrawablesCache.put(resourceUri, drawable.getConstantState()); + } + } + + /** + * Gets the left-hand side icon that will be used for the current suggestion + * if the suggestion contains an icon column but no icon or a broken icon. + * + * @param cursor A cursor positioned at the current suggestion. + * @return A non-null drawable. + */ + private Drawable getDefaultIcon1(Cursor cursor) { + // Fall back to a default icon + return mContext.getPackageManager().getDefaultActivityIcon(); + } + + /** + * Gets the activity or application icon for an activity. + * Uses the local icon cache for fast repeated lookups. + * + * @param component Name of an activity. + * @return A drawable, or {@code null} if neither the activity nor the application + * has an icon set. + */ + private Drawable getActivityIconWithCache(ComponentName component) { + // First check the icon cache + String componentIconKey = component.flattenToShortString(); + // Using containsKey() since we also store null values. + if (mOutsideDrawablesCache.containsKey(componentIconKey)) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey); + return cached == null ? null : cached.newDrawable(mProviderContext.getResources()); + } + // Then try the activity or application icon + Drawable drawable = getActivityIcon(component); + // Stick it in the cache so we don't do this lookup again. + Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState(); + mOutsideDrawablesCache.put(componentIconKey, toCache); + return drawable; + } + + /** + * Gets the activity or application icon for an activity. + * + * @param component Name of an activity. + * @return A drawable, or {@code null} if neither the acitivy or the application + * have an icon set. + */ + private Drawable getActivityIcon(ComponentName component) { + PackageManager pm = mContext.getPackageManager(); + final ActivityInfo activityInfo; + try { + activityInfo = pm.getActivityInfo(component, PackageManager.GET_META_DATA); + } catch (NameNotFoundException ex) { + Log.w(LOG_TAG, ex.toString()); + return null; + } + int iconId = activityInfo.getIconResource(); + if (iconId == 0) return null; + String pkg = component.getPackageName(); + Drawable drawable = pm.getDrawable(pkg, iconId, activityInfo.applicationInfo); + if (drawable == null) { + Log.w(LOG_TAG, "Invalid icon resource " + iconId + " for " + + component.flattenToShortString()); + return null; + } + return drawable; + } + + /** + * Gets the value of a string column by name. + * + * @param cursor Cursor to read the value from. + * @param columnName The name of the column to read. + * @return The value of the given column, or null + * if the cursor does not contain the given column. + */ + public static String getColumnString(Cursor cursor, String columnName) { + int col = cursor.getColumnIndex(columnName); + return getStringOrNull(cursor, col); + } + + private static String getStringOrNull(Cursor cursor, int col) { + if (col == INVALID_INDEX) { + return null; + } + try { + return cursor.getString(col); + } catch (Exception e) { + Log.e(LOG_TAG, + "unexpected error retrieving valid column from cursor, " + + "did the remote process die?", e); + return null; + } + } +} diff --git a/libraries/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java b/libraries/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java new file mode 100644 index 000000000..47475c574 --- /dev/null +++ b/libraries/ActionBarSherlock/test/com/actionbarsherlock/internal/ManifestParsingTest.java @@ -0,0 +1,37 @@ +package com.actionbarsherlock.internal; + +import org.junit.Test; + +import static com.actionbarsherlock.internal.ActionBarSherlockCompat.cleanActivityName; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +public class ManifestParsingTest { + @Test + public void testFullyQualifiedClassName() { + String expected = "com.other.package.SomeClass"; + String actual = cleanActivityName("com.jakewharton.test", "com.other.package.SomeClass"); + assertThat(expected, equalTo(actual)); + } + + @Test + public void testFullyQualifiedClassNameSamePackage() { + String expected = "com.jakewharton.test.SomeClass"; + String actual = cleanActivityName("com.jakewharton.test", "com.jakewharton.test.SomeClass"); + assertThat(expected, equalTo(actual)); + } + + @Test + public void testUnqualifiedClassName() { + String expected = "com.jakewharton.test.SomeClass"; + String actual = cleanActivityName("com.jakewharton.test", "SomeClass"); + assertThat(expected, equalTo(actual)); + } + + @Test + public void testRelativeClassName() { + String expected = "com.jakewharton.test.ui.SomeClass"; + String actual = cleanActivityName("com.jakewharton.test", ".ui.SomeClass"); + assertThat(expected, equalTo(actual)); + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..9df383b2a --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':OpenPGP-Keychain', ':libraries:ActionBarSherlock' -- cgit v1.2.3